Peaceful Commission

Posted Kaiser

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Peaceful Commission相关的知识,希望对你有一定的参考价值。

这道题题意就是给你n对人,一对中编号为x,x+1,给你m对矛盾,表示这两个人不能同时选。

然后就是Two-Sat的模板题了,就是根据对称性,连边,加缩点,最后拓扑排序,求出一组可行解就可以了。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<queue>
  6 #include<cstring>
  7 
  8 using namespace std;
  9 
 10 typedef pair<int,int>pai;
 11 const int NN=8007,MM=20007,INF=1e9+7;
 12 
 13 bool flag=0;
 14 int n,m;
 15 int cnt=0,head[NN*2],next[MM*2],rea[MM*2],cntr=0,headr[NN*2],nextr[MM*2],rear[MM*2];
 16 int Time,top,low[NN*2],dfn[NN*2],minnum[NN*2],stack[NN*2],instack[NN*2];
 17 int sz,belong[NN*2];
 18 int fan[NN*2],ru[NN*2];
 19 queue<int>ve[NN*2];
 20 
 21 struct Node
 22 {
 23     int x,y;    
 24 }a[MM];
 25 
 26 void add(int u,int v)
 27 {
 28     cnt++;
 29     next[cnt]=head[u];
 30     head[u]=cnt;
 31     rea[cnt]=v;
 32 }
 33 void add2(int u,int v)
 34 {
 35     cntr++;
 36     nextr[cntr]=headr[u];
 37     headr[u]=cntr;
 38     rear[cntr]=v;
 39 }
 40 void Tarjan(int u)
 41 {
 42     dfn[u]=low[u]=++Time;
 43     stack[++top]=u,instack[u]=true;
 44     for (int i=head[u];i!=-1;i=next[i])
 45     {
 46         int v=rea[i];
 47         if (dfn[v]==0)
 48         {
 49             Tarjan(v);
 50             low[u]=min(low[v],low[u]);
 51         }
 52         else if (instack[v]) low[u]=min(low[u],dfn[v]);
 53     }
 54     if (low[u]==dfn[u])
 55     {
 56         int x=-1;
 57         minnum[++sz]=INF;;
 58         while (!ve[sz].empty()) ve[sz].pop();
 59         while (x!=u)
 60         {
 61             x=stack[top--];
 62             belong[x]=sz;
 63             minnum[sz]=min(minnum[sz],x);//记录最小编号,发现对称的那个环的最小编号应该是该环最小编号的fan 
 64             ve[sz].push(x);
 65             instack[x]=false;
 66         }
 67     }
 68 }
 69 void rebuild()
 70 {
 71     for (int i=1;i<=2*n;i++)
 72         for (int j=head[i];j!=-1;j=next[j])
 73         {
 74             int v=rea[j];
 75             if (belong[i]!=belong[v])
 76             {
 77                 ru[belong[v]]++;
 78                 add2(belong[i],belong[v]);
 79             }
 80         }//重构 
 81 }
 82 bool cmp(int x,int y)
 83 {
 84     return x<y;
 85 }
 86 void solve()
 87 {
 88     int ans[NN*2];
 89     queue<int>q;
 90     while (!q.empty()) q.pop();
 91     for (int i=1;i<=sz;i++)
 92         if (!ru[i]) q.push(i);
 93     bool biao[NN*2]={0};    
 94     top=0;
 95     while(!q.empty())
 96     {
 97         int u=q.front();
 98         if (!biao[fan[minnum[u]]]) ans[++top]=u,biao[minnum[u]]=1;
 99         q.pop();
100         for (int i=headr[u];i!=-1;i=nextr[i])
101         {
102             int v=rear[i];
103             ru[v]--;
104             if (!ru[v]) q.push(v);
105         }
106     }//拓扑的一个过程 
107     bool booo=0;
108     int res[NN],ll=0;
109     for (int i=1;i<=top;i++)
110     {
111         int x=ans[i];
112         while(!ve[x].empty())
113         {
114             res[++ll]=ve[x].front();
115             ve[x].pop();    
116         }
117     }//ll最终等于n 
118     sort(res+1,res+ll+1,cmp);
119     for (int i=1;i<=ll;i++)
120         printf("%d\n",res[i]);    
121 }
122 void init()
123 {
124     cntr=cnt=top=Time=sz=flag=0;
125     memset(dfn,0,sizeof(dfn));
126     memset(head,-1,sizeof(head));
127     memset(headr,-1,sizeof(headr));
128     memset(ru,0,sizeof(ru));
129     for (int i=1;i<=2*n;i++)
130         if (i%2==1) fan[i]=i+1;
131         else fan[i]=i-1;
132     for (int i=1;i<=m;i++)
133     {
134         scanf("%d%d",&a[i].x,&a[i].y);
135         add(fan[a[i].y],a[i].x); 
136         add(fan[a[i].x],a[i].y);//刚开始连反向边并不影响正确率,而且在拓扑的时候不需要反向标记,方便许多。 
137     }
138 }
139 void pan()
140 {
141     for (int i=1;i<=2*n;i+=2)
142         if (belong[i]==belong[fan[i]])//如果一个块中,有编号一组的点,绝对不可以满足。 
143         {
144             flag=1;
145             return;
146         }
147 }
148 int main()
149 {
150     while (~scanf("%d%d",&n,&m))
151     {
152         init();//初始化非常重要。 
153         for (int i=1;i<=n*2;i++)
154             if (dfn[i]==0) Tarjan(i);//tarjan一次 
155         pan();    
156         if (flag)
157         {
158             printf("NIE\n");
159             continue;
160         }
161         rebuild();
162         solve();
163     }
164 }

 

以上是关于Peaceful Commission的主要内容,如果未能解决你的问题,请参考以下文章

Peaceful Commission

hdu1814Peaceful Commission(2-SAT)

hdu1814 Peaceful Commission

Peaceful Commission 2-sat

HDU1814 Peaceful Commission 2-sat

HDU 1814 Peaceful Commission(2-sat 模板题输出最小字典序解决方式)