[BZOJ]3495: PA2010 Riddle 2-SAT
来源:互联网 发布:社交网络的数据挖掘 编辑:程序博客网 时间:2024/05/17 08:29
Description
k个国家,几个城市,m条边。
要求每个国家有且仅有一个首都,每条边两端的城市至少要有一个首都。
判断是否有解, 有解输出“TAK”,无解输出”NIE”
1 < = k, N ,M , < =1000000。
题解:
直接建边的话边数太大,所以建多
代码:
#include<bits/stdc++.h>using namespace std;#define LL long long#define pa pair<int,int>const int Maxn=4000010;const int inf=2147483647;int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); return x*f;}struct Edge{int y,next;}e[15000010];int last[Maxn],len=0;void ins(int x,int y){int t=++len;/*printf("edge %d %d\n",y,x);*/e[t].y=y;e[t].next=last[x];last[x]=t;}int low[Maxn],dfn[Maxn],id=0,top=0,sta[Maxn],bel[Maxn],cnt=0;bool in[Maxn];void Tarjan(int x){ low[x]=dfn[x]=++id; in[x]=true;sta[++top]=x; for(int i=last[x];i;i=e[i].next) { int y=e[i].y; if(!dfn[y])Tarjan(y),low[x]=min(low[x],low[y]); else if(in[y])low[x]=min(low[x],dfn[y]); } if(low[x]==dfn[x]) { int i;cnt++; do { i=sta[top--]; in[i]=false; bel[i]=cnt; }while(i!=x); }}int n,m,k;int main(){ n=read(),m=read(),k=read(); for(int i=1;i<=m;i++) { int x=read(),y=read(); ins(y,x+n);ins(x,y+n); } for(int i=1;i<=k;i++) { int t=read(),u=-1; for(int j=1;j<=t;j++) { int x=read(); ins(x+2*n,x);ins(x+3*n,x); if(u!=-1)ins(x+2*n,u+2*n),ins(x+n,u+2*n),ins(u+3*n,x+3*n),ins(u+n,x+3*n); u=x; } } for(int i=1;i<=3*n;i++)if(!dfn[i])Tarjan(i); bool flag=false; for(int i=1;i<=n;i++) if(bel[i]==bel[i+n]){flag=true;break;} if(flag)puts("NIE"); else puts("TAK");}
阅读全文