loj 1407(2-sat + 枚举 + 输出一组可行解 )
来源:互联网 发布:声学模拟软件 编辑:程序博客网 时间:2024/05/18 22:40
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27115
思路:有一个trick要注意:当情况为 2 x y 时,可以推出当y留下时,x也必须留下。然后就是后面的k个限制关系,我们可以3^(k)次方枚举,一旦找到符合条件的就return 。然后就是反向建图,拓扑排序找可行解。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stack> 6 #include<queue> 7 #include<vector> 8 #include<cmath> 9 using namespace std; 10 #define MAXN 2222 11 12 int n,m,k; 13 struct Node{ 14 int tag; 15 int num[3]; 16 }node[7]; 17 18 vector<vector<int> >g,gg,edge; 19 20 int cnt,bcc_count; 21 int dfn[MAXN],low[MAXN],color[MAXN]; 22 int degree[MAXN]; 23 bool mark[MAXN]; 24 stack<int>S; 25 26 void Tarjan(int u) 27 { 28 low[u]=dfn[u]=++cnt; 29 mark[u]=true; 30 S.push(u); 31 for(int i=0;i<edge[u].size();i++){ 32 int v=edge[u][i]; 33 if(dfn[v]==0){ 34 Tarjan(v); 35 low[u]=min(low[u],low[v]); 36 }else if(mark[v]){ 37 low[u]=min(low[u],dfn[v]); 38 } 39 } 40 if(low[u]==dfn[u]){ 41 int v; 42 bcc_count++; 43 do{ 44 v=S.top(); 45 S.pop(); 46 mark[v]=false; 47 color[v]=bcc_count; 48 }while(u!=v); 49 } 50 } 51 52 int opp[MAXN]; 53 bool Check() 54 { 55 for(int i=1;i<=n;i++){ 56 if(color[i]==color[i+n])return false; 57 opp[color[i]]=color[i+n]; 58 opp[color[i+n]]=color[i]; 59 } 60 return true; 61 } 62 63 bool Judge() 64 { 65 int kk=(int)pow(3.0,k); 66 for(int i=0;i<kk;i++){ 67 for(int j=1;j<=2*n;j++)edge[j]=g[j]; 68 int j=i,_count=0; 69 while(_count<k){ 70 int id=j%3; 71 int x=node[_count].num[id]; 72 if(node[_count].tag==1){ 73 edge[x+n].push_back(x); 74 }else 75 edge[x].push_back(x+n); 76 _count++; 77 j/=3; 78 } 79 cnt=bcc_count=0; 80 memset(dfn,0,sizeof(dfn)); 81 memset(mark,false,sizeof(mark)); 82 for(int j=1;j<=2*n;j++)if(dfn[j]==0)Tarjan(j); 83 if(Check())return true; 84 } 85 return false; 86 } 87 88 int vis[MAXN]; 89 void TopSort() 90 { 91 queue<int>que; 92 for(int i=1;i<=bcc_count;i++){ 93 if(degree[i]==0)que.push(i); 94 } 95 memset(vis,0,sizeof(vis)); 96 while(!que.empty()){ 97 int u=que.front(); 98 que.pop(); 99 if(vis[u]==0){100 vis[u]=1;101 vis[opp[u]]=-1;102 }103 for(int i=0;i<gg[u].size();i++){104 int v=gg[u][i];105 if(--degree[v]==0)que.push(v);106 }107 }108 }109 110 vector<int>ans;111 void Solve()112 {113 gg.clear();114 gg.resize(2*n+2);115 memset(degree,0,sizeof(degree));116 for(int u=1;u<=2*n;u++){117 for(int i=0;i<edge[u].size();i++){118 int v=edge[u][i];119 if(color[u]!=color[v]){120 gg[color[v]].push_back(color[u]);121 degree[color[u]]++;122 }123 }124 }125 TopSort();126 ans.clear();127 for(int i=1;i<=n;i++)128 if(vis[color[i]]==1)ans.push_back(i);129 printf("%d",(int)ans.size());130 for(int i=0;i<(int)ans.size();i++){131 printf(" %d",ans[i]);132 }133 puts(".");134 }135 136 int main()137 {138 int _case,x,y,z,tag,t=1;139 scanf("%d",&_case);140 while(_case--){141 scanf("%d%d%d",&n,&m,&k);142 g.clear();143 g.resize(2*n+2);144 edge.clear();145 edge.resize(2*n+2);146 while(m--){147 scanf("%d%d%d",&tag,&x,&y);148 if(tag==1)g[x+n].push_back(y),g[y+n].push_back(x);149 else if(tag==2)g[x+n].push_back(y+n),g[y].push_back(x);150 else if(tag==3)g[x].push_back(y+n),g[y].push_back(x+n);151 else g[x].push_back(y+n),g[y].push_back(x+n),g[x+n].push_back(y),g[y+n].push_back(x);152 }153 for(int i=0;i<k;i++){154 scanf("%d%d%d%d",&node[i].tag,&node[i].num[0],&node[i].num[1],&node[i].num[2]);155 }156 printf("Case %d: ",t++);157 if(Judge()){158 printf("Possible ");159 Solve();160 }else 161 puts("Impossible.");162 }163 return 0;164 }165
0 0
- loj 1407(2-sat + 枚举 + 输出一组可行解 )
- loj 1251(2-sat + 输出一组可行解)
- poj 3683(2-sat+输出一组可行解)
- poj 3683 2-sat问题,输出任意一组可行解
- 2-sat 输出任意一组可行解&拓扑排序+缩点 poj3683
- Light OJ 1407 - Explosion 【2-sat之 3布尔变量的处理 — 枚举所有状态判断是否存在可行解 + 反向输出可行解】【好题】
- 2-sat模板- 输出可行解
- poj 3648 2-sat输出一组解
- poj3648 2-sat <输出任意一组解>
- poj 3648 Wedding 【2-sat 经典建图 输出一组可行解 好题】 【tarjan求SCC + 缩点 + 拓扑排序 + 染色】
- POJ 3648 Wedding (2-SAT+输出可行解)
- poj 3648 Wedding(2-sat--拓扑排序输出可行解)
- POJ 3683 2-SAT 输出可行方案
- poj 3648 2-sat 输出任意一组解模板
- Wedding (poj 3648 2-SAT 输出任意一组解)
- POJ 3648 Wedding 2-sat输出一组解
- POJ 3648 Wedding(2-SAT输出一组解)
- Light oj 1251 - Forming the Council 【2-sat】【判断是否存在可行解 + 反向拓扑输出可行解】
- uva 10246(最短路变形)
- uva 10972(边双连通分量)
- hdu 2545(并查集求节点到根节点的距离)
- hdu 4751(dfs染色)
- loj 1251(2-sat + 输出一组可行解)
- loj 1407(2-sat + 枚举 + 输出一组可行解 )
- loj 1026( tarjan + 输出割边 )
- loj 1063(求割点个数)
- loj 1300( 边双联通 + 判奇圈 )
- loj 1308(点双连通分量应用)
- loj 1108(spfa判负环)
- loj 1221(spfa判正环)
- loj 1009(dfs)
- loj 1046(bfs)