루오 구 주제 - 더 복잡한 그래프 이론 I

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;
  } 
View Code

 

추천

출처www.cnblogs.com/overrate-wsj/p/12310271.html