loj 1251(2-sat + 输出一组可行解)
来源:互联网 发布:声学模拟软件 编辑:程序博客网 时间:2024/05/17 16:00
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26961
思路:u表示留下,~u表示离开,同理v,对于+u,-v,我们可以这样来定义:若u离开,则v必须留下,如v离开,则u必须留下,于是我们可以连边u+n->v,v+n->u,后面的同理。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stack> 6 #include<vector> 7 #include<queue> 8 using namespace std; 9 #define MAXN 20000 10 #define MAXM 444444 11 12 struct Edge{ 13 int v,next; 14 }edge[MAXM]; 15 16 int n,m,NE; 17 int head[MAXN]; 18 19 void Insert(int u,int v) 20 { 21 edge[NE].v=v; 22 edge[NE].next=head[u]; 23 head[u]=NE++; 24 } 25 26 int cnt,bcc_count; 27 int low[MAXN],dfn[MAXN],color[MAXN]; 28 bool mark[MAXN]; 29 stack<int>S; 30 31 void Tarjan(int u) 32 { 33 low[u]=dfn[u]=++cnt; 34 mark[u]=true; 35 S.push(u); 36 for(int i=head[u];i!=-1;i=edge[i].next){ 37 int v=edge[i].v; 38 if(dfn[v]==0){ 39 Tarjan(v); 40 low[u]=min(low[u],low[v]); 41 }else if(mark[v]){ 42 low[u]=min(low[u],dfn[v]); 43 } 44 } 45 if(low[u]==dfn[u]){ 46 int v; 47 bcc_count++; 48 do{ 49 v=S.top(); 50 S.pop(); 51 mark[v]=false; 52 color[v]=bcc_count; 53 }while(u!=v); 54 } 55 } 56 57 int opp[MAXN]; 58 bool Judge() 59 { 60 for(int i=1;i<=n;i++){ 61 if(color[i]==color[i+n])return false; 62 //opp[x]保存的是和编号为x的连通分量矛盾的连通分量的编号 63 opp[color[i]]=color[i+n]; 64 opp[color[i+n]]=color[i]; 65 } 66 return true; 67 } 68 69 vector<vector<int> >g; 70 vector<int>ans; 71 int degree[MAXN]; 72 int vis[MAXN]; 73 74 void TopSort() 75 { 76 queue<int>que; 77 for(int i=1;i<=bcc_count;i++){ 78 if(degree[i]==0)que.push(i); 79 } 80 while(!que.empty()){ 81 int u=que.front(); 82 que.pop(); 83 if(vis[u]==0){ 84 //染色 85 vis[u]=1; 86 vis[opp[u]]=-1; 87 } 88 for(int i=0;i<g[u].size();i++){ 89 degree[g[u][i]]--; 90 if(degree[g[u][i]]==0)que.push(g[u][i]); 91 } 92 } 93 } 94 95 96 int main() 97 { 98 int _case,t=1,a,b,u,v; 99 scanf("%d",&_case);100 while(_case--){101 scanf("%d %d",&m,&n);102 NE=0;103 memset(head,-1,sizeof(head));104 while(m--){105 scanf("%d%d",&a,&b);106 u=abs(a),v=abs(b);107 if(a>0&&b>0)Insert(u+n,v),Insert(v+n,u);108 else if(a>0&&b<0)Insert(u+n,v+n),Insert(v,u);109 else if(a<0&&b>0)Insert(u,v),Insert(v+n,u+n);110 else Insert(u,v+n),Insert(v,u+n);111 }112 cnt=bcc_count=0;113 memset(mark,false,sizeof(mark));114 memset(dfn,0,sizeof(dfn));115 memset(color,0,sizeof(color));116 for(int i=1;i<=2*n;i++)if(dfn[i]==0)Tarjan(i);117 printf("Case %d: ",t++);118 if(!Judge()){119 puts("No");120 continue;121 }122 puts("Yes");123 //反向建图124 memset(degree,0,sizeof(degree));125 g.clear();126 g.resize(2*n+2);127 for(int u=1;u<=2*n;u++){128 for(int i=head[u];i!=-1;i=edge[i].next){129 int v=edge[i].v;130 if(color[u]!=color[v]){131 g[color[v]].push_back(color[u]);132 degree[color[u]]++;133 }134 }135 }136 memset(vis,0,sizeof(vis));137 TopSort();138 ans.clear();139 for(int i=1;i<=n;i++){140 if(vis[color[i]]==1)ans.push_back(i);141 }142 printf("%d",(int)ans.size());143 sort(ans.begin(),ans.end());144 for(int i=0;i<(int)ans.size();i++){145 printf(" %d",ans[i]);146 }147 puts("");148 }149 return 0;150 }
0 0
- loj 1251(2-sat + 输出一组可行解)
- loj 1407(2-sat + 枚举 + 输出一组可行解 )
- poj 3683(2-sat+输出一组可行解)
- poj 3683 2-sat问题,输出任意一组可行解
- 2-sat 输出任意一组可行解&拓扑排序+缩点 poj3683
- 2-sat模板- 输出可行解
- POJ 3648 Wedding(2-SAT输出一组解)
- poj 3648 2-sat输出一组解
- poj3648 2-sat <输出任意一组解>
- poj 3648 Wedding 【2-sat 经典建图 输出一组可行解 好题】 【tarjan求SCC + 缩点 + 拓扑排序 + 染色】
- Light oj 1251 - Forming the Council 【2-sat】【判断是否存在可行解 + 反向拓扑输出可行解】
- POJ 3648 Wedding (2-SAT+输出可行解)
- poj 3648 Wedding(2-sat--拓扑排序输出可行解)
- LightOJ 1251 Forming the Council【2-Sat+逆向拓扑排序输出可行解】好题!
- 2-sat按照最小字典序输出可行解(hdu1814)
- POJ 3683 2-SAT 输出可行方案
- poj 3648 2-sat 输出任意一组解模板
- Wedding (poj 3648 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)