zoukankan      html  css  js  c++  java
  • 【图论】【宽搜】【染色】NCPC 2014 A Ades

    题目链接:

      http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1787

    题目大意:

      N个点M条无向边(N,M<=200000),一个节点只能有一个标记。每条边有一个值{0,1或2}表示这条边连接的两个节点拥有的标记之和。问只要要多少个标记才能满足,无解impossible。

    题目思路:

      【图论】【宽搜】

      因为每个点只能有或没有标记。所以可以枚举每个联通块的其中一个点有还是没有标记,用这个点去拓展这个点的联通块并01染色(这个点所能到达的所有点)

      初始点标记为0需要的标记数为sumz,初始点为1的标记数为sumo,选取能够满足的加到答案,如果能够满足图的要求就取min。

      每个点只会被走过一次,所以是O(N)的。

      1 //
      2 //by coolxxx
      3 //#include<bits/stdc++.h>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<string>
      7 #include<iomanip>
      8 #include<map>
      9 #include<stack>
     10 #include<queue>
     11 #include<set>
     12 #include<bitset>
     13 #include<memory.h>
     14 #include<time.h>
     15 #include<stdio.h>
     16 #include<stdlib.h>
     17 #include<string.h>
     18 //#include<stdbool.h>
     19 #include<math.h>
     20 #define min(a,b) ((a)<(b)?(a):(b))
     21 #define max(a,b) ((a)>(b)?(a):(b))
     22 #define abs(a) ((a)>0?(a):(-(a)))
     23 #define lowbit(a) (a&(-a))
     24 #define sqr(a) ((a)*(a))
     25 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
     26 #define mem(a,b) memset(a,b,sizeof(a))
     27 #define eps (1e-8)
     28 #define J 10
     29 #define mod 1000000007
     30 #define MAX 0x7f7f7f7f
     31 #define PI 3.14159265358979323
     32 #define N 200004
     33 using namespace std;
     34 typedef long long LL;
     35 int cas,cass;
     36 int n,m,lll,ans;
     37 int q[N],last[N];
     38 int mark[N][2];
     39 bool u[N];
     40 struct xxx
     41 {
     42     int next,to,d;
     43 }a[N+N];
     44 void add(int x,int y,int z)
     45 {
     46     a[++lll].to=y;
     47     a[lll].d=z;
     48     a[lll].next=last[x];
     49     last[x]=lll;
     50 }
     51 bool spfa(int s)
     52 {
     53     int i,l=0,r=1,now,to,sumz=0,sumo=0;
     54     bool z=0,o=0;
     55     q[1]=s;mark[s][0]=0,mark[s][1]=1;u[s]=1;
     56     while(l!=r)
     57     {
     58         now=q[l=(l+1)%N];
     59         sumz+=mark[now][0];sumo+=mark[now][1];
     60         for(i=last[now];i;i=a[i].next)
     61         {
     62             to=a[i].to;
     63             if(mark[to][0]==-1)mark[to][0]=a[i].d-mark[now][0];
     64             if(mark[to][1]==-1)mark[to][1]=a[i].d-mark[now][1];
     65             if(mark[now][0]+mark[to][0]!=a[i].d || mark[to][0]<0 || mark[to][0]>1)z=1;
     66             if(mark[now][1]+mark[to][1]!=a[i].d || mark[to][1]<0 || mark[to][1]>1)o=1;
     67             if(!u[to])
     68             {
     69                 u[to]=1;
     70                 q[r=(r+1)%N]=to;
     71             }
     72         }
     73         if(z && o)break;
     74     }
     75     if(z && o)return 0;
     76     if(!z && o)ans+=sumz;
     77     else if(z && !o)ans+=sumo;
     78     else if(!z && !o)ans+=min(sumz,sumo);
     79     return 1;
     80 }
     81 int main()
     82 {
     83     #ifndef ONLINE_JUDGE
     84 //    freopen("1.txt","r",stdin);
     85 //    freopen("2.txt","w",stdout);
     86     #endif
     87     int i,j,k;
     88     int x,y,z;
     89 //    for(scanf("%d",&cass);cass;cass--)
     90 //    for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
     91 //    while(~scanf("%s",s+1))
     92     while(~scanf("%d",&n))
     93     {
     94         mem(u,0);mem(mark,-1);
     95         scanf("%d",&m);
     96         for(i=1;i<=m;i++)
     97         {
     98             scanf("%d%d%d",&x,&y,&z);
     99             add(x,y,z);
    100             add(y,x,z);
    101         }
    102         ans=0;
    103         for(i=1;i<=n;i++)
    104         {
    105             if(u[i])continue;
    106             if(!spfa(i))break;
    107         }
    108         if(i<=n)puts("impossible");
    109         else printf("%d
    ",ans);
    110     }
    111     return 0;
    112 }
    113 /*
    114 //
    115 
    116 //
    117 */
    View Code
  • 相关阅读:
    HDU 3951 (博弈) Coin Game
    HDU 3863 (博弈) No Gambling
    HDU 3544 (不平等博弈) Alice's Game
    POJ 3225 (线段树 区间更新) Help with Intervals
    POJ 2528 (线段树 离散化) Mayor's posters
    POJ 3468 (线段树 区间增减) A Simple Problem with Integers
    HDU 1698 (线段树 区间更新) Just a Hook
    POJ (线段树) Who Gets the Most Candies?
    POJ 2828 (线段树 单点更新) Buy Tickets
    HDU 2795 (线段树 单点更新) Billboard
  • 原文地址:https://www.cnblogs.com/Coolxxx/p/5827345.html
Copyright © 2011-2022 走看看