BZOJ3495: PA2010 Riddle

$n \leq 1e6,m \leq 1e6$的无向图,每个点属于一个国家(我就说国家咋地),现要求给所有$k$个国家分别选首都,满足:每条边至少一个端点是首都;每个国家有且只有一个首都。

2-SAT。每个点选和不选。条件一直接满足,条件二边数太多。

前缀优化建边。来源

 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 }
View Code

 

posted @ 2018-04-24 21:55  Blue233333  阅读(273)  评论(0编辑  收藏  举报