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

 P1330 封锁阳光大学

题目描述

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

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

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

输入输出格式

输入格式:

 

第一行:两个整数N,M

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

 

输出格式:

 

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

 

输入输出样例

输入样例#1:
【输入样例1】
3 3
1 2
1 3
2 3

【输入样例2】
3 2
1 2
2 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 }
posted @ 2017-06-26 18:20  MJT12044  阅读(313)  评论(0编辑  收藏  举报