Description
\(n\)个城市,\(k\)个国家,\(m\)条边,边两边至少有一个首都,问是否存在合法解。\(1\leqslant k\leqslant n,m\leqslant 10^6\)
Solution
2-SAT.
有几个限制条件一起列上...
这样建图是\(O(n^2)\)的...用前缀和表示来限制一下首都个数...
1.一个点不是首都,那么另一个点一定是首都.
2.前缀和为1,这个点一定为0.
3.这个点为1,前缀和一定为1.
4.这个点为1,前一个点一定为0.
5.这个位置的前缀和为0,前一个位置的前缀和一定为0.
6.这个位置的前缀和为1,后一个位置的前缀和一定为1.
然后缩点判断一下...用vector被卡常了...
Code
/**************************************************************
Problem: 3495
User: BeiYu
Language: C++
Result: Accepted
Time:20436 ms
Memory:350776 kb
****************************************************************/
#include <bits/stdc++.h>
using namespace std;
const int N = 4000050;
const int M = 20000050;
inline int in(int x=0,char c=getchar()) { while(c>'9'||c<'0') c=getchar();
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();return x; }
int n,k,m,cp,bp,tp;
int a[N];
int b[N],bl[N],dfn[N],low[N],stk[N];
int ep;
int nxt[M],tto[M],hd[M];
void AddEdge(int fr,int to) { nxt[++ep]=hd[fr],tto[ep]=to,hd[fr]=ep; }
void Tarjan(int u,int fa) {
dfn[u]=low[u]=++cp,b[u]=1,stk[++tp]=u;
for(int i=hd[u],v;i;i=nxt[i]) {
v=tto[i];
if(!dfn[v]) Tarjan(v,u),low[u]=min(low[u],low[v]);
else if(b[v]) low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u]) {
for(bp++;;) {
int v=stk[tp];
bl[v]=bp,b[v]=0,tp--;
if(u==v) break;
}
}
}
int main() {
n=in(),m=in(),k=in();
for(int i=1;i<=m;i++) {
int u=in(),v=in();
AddEdge(u,v+n);
AddEdge(v,u+n);
}
for(int i=1,t,j;i<=k;i++) {
for(t=in(),j=1;j<=t;j++) a[j]=in();
for(j=1;j<=t;j++) {
if(j+1<=t)
AddEdge(a[j+1]+2*n,a[j]+2*n),AddEdge(a[j]+3*n,a[j+1]+3*n),
AddEdge(a[j]+3*n,a[j+1]),AddEdge(a[j+1]+n,a[j]+2*n);
AddEdge(a[j]+n,a[j]+3*n),AddEdge(a[j]+2*n,a[j]);
}
}
for(int i=1;i<=4*n;i++) if(!dfn[i]) Tarjan(i,i);
/* for(int i=1;i<=4*n;i++) {
cout<<i<<" --> ";
for(int j=0;j<(int)g[i].size();j++) cout<<g[i][j]<<" ";cout<<endl;
}
for(int i=1;i<=4*n;i++) cout<<dfn[i]<<" ";cout<<endl;
for(int i=1;i<=4*n;i++) cout<<low[i]<<" ";cout<<endl;
for(int i=1;i<=4*n;i++) cout<<bl[i]<<" ";cout<<endl;*/
for(int i=1;i<=n;i++) if(bl[i]==bl[i+n]) return puts("NIE"),0;
for(int i=2*n+1;i<=3*n;i++) if(bl[i]==bl[i+n]) return puts("NIE"),0;
return puts("TAK"),0;
}