首页 > 代码库 > P1330 封锁阳光大学(染色问题)

P1330 封锁阳光大学(染色问题)

 P1330 封锁阳光大学

题目描述

曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街。河蟹看到欢快的曹,感到不爽。河蟹决定封锁阳光大学,不让曹刷街。

阳光大学的校园是一张由N个点构成的无向图,N个点之间由M条道路连接。每只河蟹可以对一个点进行封锁,当某个点被封锁后,与这个点相连的道路就被封锁了,曹就无法在与这些道路上刷街了。非常悲剧的一点是,河蟹是一种不和谐的生物,当两只河蟹封锁了相邻的两个点时,他们会发生冲突。

询问:最少需要多少只河蟹,可以封锁所有道路并且不发生冲突。

输入输出格式

输入格式:

 

第一行:两个整数N,M

接下来M行:每行两个整数A,B,表示点A到点B之间有道路相连。

 

输出格式:

 

仅一行:如果河蟹无法封锁所有道路,则输出“Impossible”,否则输出一个整数,表示最少需要多少只河蟹。

 

输入输出样例

输入样例#1:
【输入样例1】3 31 21 32 3【输入样例2】3 21 22 3
输出样例#1:
【输出样例1】Impossible【输出样例2】1

说明

【数据规模】

1<=N<=10000,1<=M<=100000,任意两点之间最多有一条道路。

因为河蟹很不和谐,相邻的点是不能有河蟹的,也就是相邻的点的状态不能相同,这个问题就是染色问题: 
对于一个点,可以它染成黑色或者白色,所以从第一个可染色的点开始染色,将它染成黑的或者是白的,之后搜索将整张图都染色,统计被染色的黑色总数和白色总数,在两者中取min即是最小放河蟹的数目。 
注意:1、由于图不一定是联通的,搜索多次。2、M<=100000,开200000,双向建边,QAQ。

 1 #include<cstdio> 2 #include<queue> 3 #include<cstdlib> 4 #include<algorithm> 5 using namespace std; 6  7 const int MAXN = 10100; 8 struct Edge{ 9     int to,nxt;10 }e[200100];    //双向边乘2 11 int col[MAXN],head[MAXN];12 int n,m,cnt,ans;13 queue<int>q;14 15 void add(int u,int v)16 {17     ++cnt;18     e[cnt].to = v;19     e[cnt].nxt = head[u];20     head[u] = cnt;21 }22 23 int bfs(int a)24 {25     int ans1 = 0, ans2 = 0;26     col[a] = 1;27     ans1++;28     q.push(a); 29     while (!q.empty())30     {31         int u = q.front();32         q.pop();33         for (int i=head[u]; i; i=e[i].nxt)34         {35             int v = e[i].to;36             if (col[v]==0) 37             {38                 if (col[u]==1) col[v] = 2, ans2++;39                 else if (col[u]==2) col[v] = 1, ans1++;40                 q.push(v);41             }42             else if (col[v]==col[u])43             {44                 printf("Impossible");45                 exit(0);46             }47         }48     }49     return min(ans1,ans2);50 }51 52 int main()53 {54     scanf("%d%d",&n,&m);55     for (int x,y,i=1; i<=m; ++i)56     {57         scanf("%d%d",&x,&y);58         add(x,y);59         add(y,x);60     }61     for (int i=1; i<=n; ++i)62         if (!col[i]) ans += bfs(i);63     printf("%d",ans);64     return 0;65 }

dfs代码简短一些,注意第29行。

 1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4  5 const int MAXN = 10100; 6 struct Edge{ 7     int to,nxt; 8 }e[200100];    //双向边乘2  9 int col[MAXN],head[MAXN];10 bool vis[MAXN],flag = true; 11 int n,m,cnt,ans,ans1,ans2;12 13 void add(int u,int v)14 {15     ++cnt;16     e[cnt].to = v;17     e[cnt].nxt = head[u];18     head[u] = cnt;19 }20 21 void dfs(int u,int c)22 {23     vis[u] = true;24     if (c==1) col[u]=2, ans2++;25     else if (c==2) col[u] = 1, ans1++;26     for (int i=head[u]; i; i=e[i].nxt)27     {28         int v = e[i].to;29         if (vis[v])    //不能写成if(vis[i]&&col[u]==col[v]),影响到else的执行 30         {31             if (col[v]==col[u])32                 flag = false;33         }34         else dfs(v,col[u]);35     }36 }37 int main()38 {39     scanf("%d%d",&n,&m);40     for (int x,y,i=1; i<=m; ++i)41     {42         scanf("%d%d",&x,&y);43         add(x,y);44         add(y,x);45     }46     for (int i=1; i<=n; ++i)47         if (!vis[i])48         {49             ans1 = ans2 = 0;50             dfs(i,1);51             if (flag) ans += min(ans1,ans2);52             else break;53         }54     if (flag) printf("%d",ans);55     else printf("Impossible");56     return 0;57 }

P1330 封锁阳光大学(染色问题)