P1268 나무 무게 (사고 제목)
질문의 의미 :
첫째, 여러 권리의 무게의 각면에 지금 당신과 각 리프 노드 사이의 최단 거리에 나무의 정의, 그래서 당신은 나무의 무게를 찾을 수 있음
아이디어 :
리프 노드 간의 거리를 정의한다 DIS [U, V]
우리가 처음 두 개의 노드 만의 경우를 고려할 것입니다 그래서, 그 대답은 창피 [U, V]
각 노드는 그 노드 (3)는 연결 1 및도 2에 단지 하나의 에지에 의해 접속되는 리프 노드이기 때문에 경우 N = 3, 우리는, 트리 (3)에 추가 된 노드의 수를 고려할
길이 = LEN / 2 (DIS (1,3) + DIS는 (2,3) (1,2) -dis)
N> 3의 경우도 동일한 이유이다. 열거 나, n은 경로의 관점에서 분기되는 지점에 보지된다 ~ 난 렌 최소 대답의 내부에인가되는 판단
사용법 #include <iostream> #INCLUDE <알고리즘> #INCLUDE <CString을> #INCLUDE <cstdio> #DEFINE INF 0x3f3f3f3f 사용 공간을 성병; CONST INT maxn = 35 ; INT의 DIS [maxn] maxn]; 값 int ) (주 { INT , N (X)를; 반면 (는 scanf ( " %의 D ' , N) && N) { memset 함수 (DIS, 0 , 는 sizeof (DIS)); 위한 ( INT 난 = 1 ; I <N; ++ i)는 { 대 ( INT J = 나 + 1 , J <= N; ++ j)는 { 는 scanf ( " %의 D ' , X); DIS [I] [J] = X, DIS [J] [I] = (X); } } INT ANS DIS = [ 1 ] [ 2 ]; 위한 ( INT 난 = 3 ; I <= N; I ++ ) { INT LEN = INF; 대 ( INT J = 1 ; J <I, J ++ ) { 대 ( INT에 K = 1, K <J, K ++ ) LEN = 분 (렌 (DIS [I] [J] + DIS [K] [I] -dis [K] [J]) >> 1 ); } ANS + = LEN; } COUT << ANS << ENDL; } }
P1113 가사 (위상 정렬)
질문의 의미 :
N 작업이 있으며, 각각의 필요한 완료 시간을 가지고, 그것의 전임자는 모든 작업을 완료하는 데,이 (직접 동시에 시작할 수 있습니다 작업과 관련이없는) 얼마나 오래 요청
아이디어 :
자신의의 조금 더 복잡 비트 쓰기
먼저 전임자 (정면에서 심지어 그들 자신)도 감독 가장자리의 모든 임무를 들면,지도에 내장하고, 기록 포인트로 읽어
다시 이송하기 전에 0 도의 점은 큐에 추가되는 감소 정도에있는 모든 인접하는 에지 점, 만약 0 점의 정도, 큐의 또
더 중요한 점은 업데이트하는 방법이다 [NEX = 최대 DP (DP [NEX, DP [I] + 팀 [NEX])
내 서면으로 직접 배열을 해결할 수있을 것 DP와 시간을 저장 한 개 이상의 큐와 함께, 더 복잡
사용법 #include <iostream> #INCLUDE <알고리즘> #INCLUDE <큐> #INCLUDE <벡터> #INCLUDE <cstdio> #INCLUDE <CString을> #DEFINE INF 0x3f3f3f3f 사용 공간을 성병; CONST INT maxn 1E5 + = 10 ; 큐 < INT > A, B; 벡터 < INT > 에지 [maxn]; INT 의 [maxn, 팀 [maxn, ANS, N, MX [maxn]; 무효 ) (해결 { 위해은 ( INT는 난 = 1 ; I <= N; 나는 ++) { 경우 (! 에 [I]) { a.push (I) b.push TIM ([I]); } } 하면서 (! a.empty는 ()) { INT (X) = a.front ()는 Y = () b.front 단계; () ()를 b.pop a.pop; ANS = 최대 (ANS, Y); 위한 ( INT 난 = 0 ; I <에지 [X] 크기는 (); I ++ ) { 에서 [에지 [X] [I] - ; MX [에지 [X] [I] = 최대 (Y, MX [에지 [X] [I]); 만약 (! 에서 [에지 [X] [I]) { a.push (에지 [X] [I]); b.push (팀 [에지 [X] [I]+ MX [에지 [X] [I]); } } } } INT 의 main () { INT (X), (Y), 온도; scanf와 ( " %의 D ' , N); 위한 ( INT 난 = 1 ; I <= N; I ++ ) { 는 scanf ( " % D % D ' , X, Y); 팀 [X] = Y; 반면 (는 scanf ( " %의 D " , 및 온도) && TEMP) { 에지 [임시] .push_back (X); 의 [X] ++ ; } memset 함수 (MX, -INF, 는 sizeof (MX)); ANS = - INF; 풀다(); COUT << ANS << ENDL; }
P1525은 (분형 그래프 / 이산 세트) 범죄자 유지
질문의 의미 :
사용자는 각각의 X와 관련된 각각의 관계, Y 개의 모순되는 값 w 모순 관계를 해요
판사는, x와 y의 두 세트를 피하기 충돌하는 기능을 할당하십시오
충돌은, 제발 작은 모순 출력 값이 불가피한 경우, 0으로 출력을 피하십시오
아이디어 :
방법 ① : 분리 된 세트
, 연결, 전송 저항, 쉽게 설명하자면를 유지할 수 연결되지 않은 세트 亲戚的亲戚是亲戚
.
우리는 생각 두 사람이, 원한 B, 그래서 분명히 싸움이 될 것입니다 함께 넣어, 우리뿐만 아니라 함께 A와 B의 다른 원수를 넣을 수 있습니다,
이러한 상황이 발생할 수의 때문에, B 반대 그들은이 같은 모음에 배치 할 수 있습니다, B 및 기타 원수 사이 단지 모순, 그리고 그는 "적의 적은 나의 친구입니다".
당신이 상충되는 경우를 보장 할 수 있도록 우리는, 체중 내림차순 사이의 관계를 따라 갈 수 없어, 대답은 최소화
모든 관계 첨가를 위해, 우리는 먼저 충돌, 직접 출사 대답의 말 보인다면들이 동일한 집합에 있는지 판단
사용법 #include <iostream> #INCLUDE <알고리즘> #INCLUDE <CString을> #INCLUDE <cstdio> 사용 공간을 성병; CONST INT maxn1 = 2e4 + (10) ; CONST INT maxn2 1E5 + = 10 ; INT [maxn1] FA, 엔 [maxn1]; 구조체 노드 { INT U, V, w; } 에지 [maxn2]; INT의 발견 ( INT X) { 복귀 FA [X] == X X : FA ([X] = 찾을 FA ([X]));} INT의 CMP (노드 A, 노드 B) { 창 AW> BW} INT ) (주 { INT의 N, m; scanf와 ( " % D % D " , 및 N, m); 위한 ( INT 난 = 1 는 scanf (; I <= m I ++) " % D % D % D " , 에지 [I] .u, 에지 [I] .V, 에지 [I] .W)를; 위한 ( INT 난 = 1 ; I <= N; I ++) FA [I] = I; memset 함수 (엔, 0 , 는 sizeof (엔)); 정렬 (에지 + 1 에지 + 1 + m, CMP); 위한 ( INT 난 = 1 ; I <= m I ++ ) { INT유 = w 에지 [I] .u, V = 가장자리 [I] .V = 가장자리 [I] .W 단계; INT F1 = 발견 (U), F2 = 발견 (V); 경우 (F1 == F2) { COUT << << w ENDL; 반환 0 ; } 다른 { 경우 (! 엔 [U]) 엔 [U] = V; 다른 FA [발견 (엔 [U]) = 찾기 (V); 경우 (엔 [V]!) 엔 [V] = U; 다른 FA [발견 (엔이 [V]) = (U) 발견; } } COUT << 0 << ENDL; 반환 0 ; }
방법 ② : 양자도.
두 그룹으로 나누어 수감자를 참조하십시오 이분 그래프의 관행을 생각 쉬워야한다
이 모든 경우는 두 부분으로 모든 죄수를 대변 할 수있는 몇 가지 충돌이 피할 수없는이 있어야 것이 분명하다
우리는 또한 우리가 연습의 절반 생각할 수, 충돌이 모노톤이므로주의 수
현재 중반의 절반의 가치를 제공하는 우리 진 대답은 두 가지 모순 어떤 경우 x와 y는 두 개의 서로 다른 세트로 나눌 수 있어야 모두는 노드와 범죄자, 중간 값 사이의 갈등은 더욱 범죄에 해당 면, 우리는 무향 그래프를 얻을. 그것이 된 그래프의 경우,이 시점에서, 우리는 단지,이 방향성이 분형 그래프 (인해 두 부분으로) 할 수 있는지 여부를 결정되도록 우측 절반 포인트 R = 중간, 또는 L을 할 = 중간
#include<iostream> #include<algorithm> #include<cstring> #include<queue> #include<cstdio> using namespace std; const int maxn=2e5+10; struct edge{ int u,v,w; }p[maxn]; int n,m,L=0,R=0,cnt=0,head[maxn]; void add_edge(int x,int y,int w) { p[++cnt].u=head[x]; head[x]=cnt; p[cnt].v=y; p[cnt].w=w; } bool judge(int mid) { queue<int> q; int color[maxn]={0}; for(int i=1;i<=n;i++){ if(!color[i]) color[i]=1,q.push(i); while(!q.empty()){ int x=q.front(); q.pop(); for(int j=head[x];j;j=p[j].u){ if(p[j].w>=mid){ if(!color[p[j].v]){ q.push(p[j].v); if(color[x]==1) color[p[j].v]=2; else color[p[j].v]=1; } else if(color[p[j].v]==color[x]) return false; } } } } return true; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); R=max(R,w); add_edge(u,v,w); add_edge(v,u,w); } int ans=0; R++; while(L+1<R){ int mid=(L+R)>>1; if(judge(mid)) R=mid; else L=mid; } cout<<L<<endl; return 0; }