HDU 1814(染色)

xiaoxiao2021-02-28  165

题目大意

有n个党派,每个党派2个人,这2*n个人之间存在一些敌对关系,现在要从中选出n个人组成一个委员会,要求满足: 1.每个党派中选1个 2.委员会中不存在敌对关系

分析

题目中第i个党派的成员编号是2n-1与2n,我们将编号减去1就可以通过x^1来得到和x在相同党派的另一个人了。如果a与b敌对,那么a一定与b^1相同颜色。 用染色法来解决这个问题,设1为选中的颜色,2为不选的颜色。 这样我们从一个未被染色的节点x出发将它染为1,并通过深搜将和它颜色相同的节点y染为1,并将y ^1染为2. 如果出现矛盾则将从x节点出发的节点颜色全部清零,将x染为2看是否可行,若不可行则问题无解。

代码

#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #include<cstdlib> #include<queue> #include<map> #include<algorithm> #include<set> #include<stack> using namespace std; const int MAXN=160005; const int MAXM=200005; int col[MAXN];//col[i]为1表示选中,为0表示不选 int now[MAXN];//保存当前轮染色过程中的节点编号 int cnt; int n,m; struct Edge { int v; int next; }edge[MAXM]; int edgecount; int head[MAXN]; void Init() { edgecount=0; memset(head,-1,sizeof(head)); } void Add_edge(int u,int v) { edge[++edgecount].v=v; edge[edgecount].next=head[u]; head[u]=edgecount; } bool Paint(int x)//染色成功返回1否则返回0 { if(col[x]==2)return 0; if(col[x]==1)return 1; col[x]=1;col[x^1]=2; now[++cnt]=x; for(int k=head[x];k!=-1;k=edge[k].next) { int v=edge[k].v; if(!Paint(v))return 0; } return 1; } bool Work()//如果存在可行解返回1否则返回0 { memset(col,0,sizeof(col)); for(int u=0;u<n*2;u++) { if(col[u])continue; cnt=0; if(!Paint(u)) { for(int j=1;j<=cnt;j++) { col[now[j]]=0; col[now[j]^1]=0; } if(!Paint(u^1)){return 0;} } } return 1; } int main() { int a,b; while(scanf("%d%d",&n,&m)!=EOF) { Init(); for(int i=1;i<=m;i++) { scanf("%d%d",&a,&b); a--;b--; Add_edge(a,b^1); Add_edge(b,a^1); } memset(col,0,sizeof(col)); if(Work())//染色成功 { for(int i=0;i<n*2;i++) if(col[i]==1)cout<<i+1<<endl; } else cout<<"NIE"<<endl; } return 0; }
转载请注明原文地址: https://www.6miu.com/read-18425.html

最新回复(0)