由 对 称 性 解 2 - S A T 问 题 - 博 客 园
一、建立有向圖。
二、尋找所有Strongly Connected Component。
三、收縮每個Strongly Connected Component,成為有向無環圖DAG。
四、尋找縮圖的Topological Ordering。
五、在縮圖上,以Topological Ordering的反序,列出解。
* N个集团,每个集团2个人(0<=ni<2n p="p">2n>
* 且每个集团只能选出一个人。如果两人有矛盾,他们不能同时被选中
* 问最多能选出多少人並列出
sample input:
3 4 (N M) (N組人M組條件)
1 2 (第1組)
3 4
5 6 (第3組)
1 3 (第1條件: 1不與3同時選上)
1 5
2 3
2 4
//reference: 演算法筆記 http://www.csie.ntnu.edu.tw/~u91029/SimulationModeling.html#a6
#include<stdio.h>
#include<string.h>
#include<iostream>
#define DBG 1
using namespace std;
int visit[20],map[20][20];
int sat[20];
int finish[20], scc[20], n, N;
int f[20],x[20],y[20];
void DFS1(int i)
{
visit[i] = true;
for (int j=0; j<N+N; ++j)
if (map[i][j] && !visit[j])
DFS1(j);
finish[n++] = i;
}
void DFS2(int i)
{
scc[i] = n;
if(DBG)printf("scc[%d]=%d\n",i+1,n);
visit[i] = true;
for (int j=0; j<N+N; ++j)
if (map[j][i] && !visit[j]){
DFS2(j);
}
}
void two_satisfiability()
{
n = 0; // 時刻
memset(visit, false, sizeof(visit));
for (int i=0; i<N; ++i)
if (!visit[i])
DFS1(i);
memset(visit, false, sizeof(visit));
for (int k=N-1; k>=0; --k)
{
int i = finish[k];
if (!visit[i])
DFS2(i), n++;
}
// 檢查是否有解,無解則立即結束。
for (int i=0; i<N; ++i)
if (scc[i] == scc[f[i]])
return;
// 找出一組解
memset(sat, 0, sizeof(sat));
for (int k=0; k<N; ++k)
{
int i = finish[k];
if (!sat[scc[i]])
{
sat[scc[i]] = 1;
sat[scc[f[i]]] = 2;
}
}
// 印出一組解
for (int i=0; i<N; ++i)
if (sat[scc[i]] == 1)
cout << i+1 <<endl;
}
int main(){
int m;
while (scanf("%d%d",&N,&m)!=EOF && N+m){
int p,q;
for (int i=0;i<N;i++){
scanf("%d%d",&p,&q),p--,q--;
f[p]=q,f[q]=p;
}
for (int i=0;i<m;i++) scanf("%d%d",&p,&q),p--,q--,x[i]=p,y[i]=q;
for (int i=0;i<m;i++){
map[x[i]][f[y[i]]]=map[y[i]][f[x[i]]]=1;
}
N*=2;
two_satisfiability();
}
return 0;
}
沒有留言:
張貼留言