HDU1814 Peaceful Commission
Time Limit: 5000MS | Memory Limit: 32768KB | 64bit IO Format: %I64d & %I64u |
Description
The Public Peace Commission should be legislated in Parliament of The Democratic Republic of Byteland according to The Very Important Law. Unfortunately one of the obstacles is the fact that some deputies do not get on with some others.
The Commission has to fulfill the following conditions:
1.Each party has exactly one representative in the Commission,
2.If two deputies do not like each other, they cannot both belong to the Commission.
Each party has exactly two deputies in the Parliament. All of them are numbered from 1 to 2n. Deputies with numbers 2i-1 and 2i belong to the i-th party .
Task
Write a program, which:
1.reads from the text file SPO.IN the number of parties and the pairs of deputies that are not on friendly terms,
2.decides whether it is possible to establish the Commission, and if so, proposes the list of members,
3.writes the result in the text file SPO.OUT.
The Commission has to fulfill the following conditions:
1.Each party has exactly one representative in the Commission,
2.If two deputies do not like each other, they cannot both belong to the Commission.
Each party has exactly two deputies in the Parliament. All of them are numbered from 1 to 2n. Deputies with numbers 2i-1 and 2i belong to the i-th party .
Task
Write a program, which:
1.reads from the text file SPO.IN the number of parties and the pairs of deputies that are not on friendly terms,
2.decides whether it is possible to establish the Commission, and if so, proposes the list of members,
3.writes the result in the text file SPO.OUT.
Input
In the first line of the text file SPO.IN there are two non-negative
integers n and m. They denote respectively: the number of parties, 1
<= n <= 8000, and the number of pairs of deputies, who do not like
each other, 0 <= m <=2 0000. In each of the following m lines
there is written one pair of integers a and b, 1 <= a < b <=
2n, separated by a single space. It means that the deputies a and b do
not like each other.
There are multiple test cases. Process to end of file.
There are multiple test cases. Process to end of file.
Output
The text file SPO.OUT should contain one word NIE (means NO in Polish),
if the setting up of the Commission is impossible. In case when setting
up of the Commission is possible the file SPO.OUT should contain n
integers from the interval from 1 to 2n, written in the ascending order,
indicating numbers of deputies who can form the Commission. Each of
these numbers should be written in a separate line. If the Commission
can be formed in various ways, your program may write mininum number
sequence.
Sample Input
3 2
1 3
2 4
Sample Output
1
4
5
Source
POI 2001
基本2-sat问题练习。每个集合里有两个点,两个点中至少要选一个,有些点不能同时选择。
类似于并查集解关押罪犯、食物链等题时用到的“镜像点”,若是选了一个点,就不能选它的镜像点,若选了镜像点,就不能选它的本体,在2-sat中,也用这样的方式处理每一个点。
2-sat中,通过在图上连边的方式来限制选择:若是选了一个点,那么和这个点连接的所有点都要选择。
设两个点a、b的镜像点分别是a',b',若要表示“选了a就不能选b”,就从a到b'连一条边,这样,若是选了a,就只能选b',而b'和b不能同时选,达到了限制目的。
同理有各种表示选择关系的方法:
A和B不能同时取
A连B’,B连A’
A和B不能同时不取
A’连B,B’连A
AB要么都取要么都不取
A连B,B连A,A’连B’,B’连A’
点A必须取
A’连A(自己和镜像点不能同时取,这么连必然导致选A'的可能不成立,所以就只能选A)
另附一个写得很棒的讲解:http://blog.csdn.net/jarjingx/article/details/8521690
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 const int mxn=50000; 7 struct edge{ 8 int to; 9 int next; 10 }e[mxn]; 11 int hd[mxn],cnt=0; 12 int n,m; 13 int vis[mxn]; 14 int st[mxn],top=0; 15 void add_edge(int u,int v){ 16 e[++cnt].next=hd[u];e[cnt].to=v;hd[u]=cnt; 17 } 18 bool dfs(int x){ 19 if(vis[x^1])return 0;//对应点已经使用 20 if(vis[x])return 1; 21 // 22 vis[x]=1; 23 st[++top]=x; 24 for(int i=hd[x];i!=-1;i=e[i].next) 25 if(!dfs(e[i].to))return 0;//路径不能全部满足 26 return 1; 27 } 28 bool tsat(int n){ 29 memset(vis,0,sizeof vis); 30 for(int i=0;i<n;i+=2){ 31 if(vis[i]||vis[i^1])continue; 32 top=0; 33 if(!dfs(i)){// 34 while(top)vis[st[top--]]=0; 35 if(!dfs(i^1))return 0;//如果该sat的两个点都不能选,说明无解 36 } 37 } 38 return 1; 39 } 40 int main(){ 41 while(scanf("%d%d",&n,&m)!=EOF){ 42 cnt=0; 43 memset(hd,-1,sizeof hd); 44 int i,j; 45 int u,v; 46 for(i=1;i<=m;i++){ 47 scanf("%d%d",&u,&v); 48 u--; v--; 49 add_edge(u,v^1);//不能同时选 50 add_edge(v,u^1); 51 } 52 n*=2; 53 if(tsat(n)){ 54 for(int i=0;i<n;i++){ 55 if(vis[i])//如果2sat判断可行,那么已经标记出了可行路线 56 printf("%d\n",i+1); 57 } 58 } 59 else printf("NIE\n"); 60 } 61 return 0; 62 }
本文为博主原创文章,转载请注明出处。