$n leq 1e6,m leq 1e6$的无向图,每个点属于一个国家(我就说国家咋地),现要求给所有$k$个国家分别选首都,满足:每条边至少一个端点是首都;每个国家有且只有一个首都。
2-SAT。每个点选和不选。条件一直接满足,条件二边数太多。
前缀优化建边。来源
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 //#include<time.h> 5 //#include<complex> 6 //#include<set> 7 //#include<queue> 8 #include<algorithm> 9 #include<stdlib.h> 10 using namespace std; 11 12 #define LL long long 13 int qread() 14 { 15 char c; int s=0; while ((c=getchar())<'0' || c>'9'); 16 do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s; 17 } 18 19 //Pay attention to '-' , LL and double of qread!!!! 20 21 int n,m,K; 22 #define maxn 4000011 23 #define maxm 10000011 24 struct Edge{int to,next;}; 25 struct Graph 26 { 27 Edge edge[maxm]; int first[maxn],le; 28 Graph() {le=2;} 29 void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;} 30 void insert(int x,int y) {in(x,y); in(y,x);} 31 }g; 32 33 int bel[maxn],tot,Time,low[maxn],dfn[maxn],sta[maxn],top; bool insta[maxn]; 34 void tarjan(int x) 35 { 36 low[x]=dfn[x]=++Time; 37 sta[++top]=x; insta[x]=1; 38 for (int i=g.first[x];i;i=g.edge[i].next) 39 { 40 Edge &e=g.edge[i]; 41 if (!dfn[e.to]) tarjan(e.to),low[x]=min(low[x],low[e.to]); 42 else if (insta[e.to]) low[x]=min(low[x],dfn[e.to]); 43 } 44 if (low[x]==dfn[x]) 45 { 46 tot++; 47 while (sta[top]!=x) insta[sta[top]]=0,bel[sta[top]]=tot,top--; 48 insta[sta[top]]=0,bel[sta[top--]]=tot; 49 } 50 } 51 bool check() 52 { 53 for (int i=1;i<=n;i++) if (bel[i]==bel[i+n] || bel[i+2*n]==bel[i+3*n]) return 0; 54 return 1; 55 } 56 57 int main() 58 { 59 n=qread(); m=qread(); K=qread(); 60 for (int i=1,x,y;i<=m;i++) 61 { 62 x=qread(); y=qread(); 63 g.in(x+n,y); g.in(y+n,x); 64 } 65 for (int i=1,x,y,p;i<=K;i++) 66 { 67 x=qread(); p=0; 68 for (int j=1;j<=x;j++) 69 { 70 y=qread(); 71 g.in(y,y+2*n); g.in(y+3*n,y+n); 72 if (p) 73 { 74 g.in(p+2*n,y+2*n); 75 g.in(y+3*n,p+3*n); 76 g.in(p+2*n,y+n); 77 g.in(y,p+3*n); 78 } 79 p=y; 80 } 81 } 82 for (int i=1,to=4*n;i<=to;i++) if (!dfn[i]) tarjan(i); 83 puts(check()?"TAK":"NIE"); 84 return 0; 85 }