【2-SAT(两次DFS版)】BZOJ1823-[JSOI2010]满汉全席
【题目大意】
有n个材料,m个评委。每种材料可以被用来做满族菜或汉族菜,m个评委有两种可以让他满意的猜中。问是否可以满足所有评委要求?
【思路】
每天只能做三道题,我已经是一个废人了……(葛优躺.jpg)
裸2-SAT,先写了个两遍DFS的,速度略慢……24ms?
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 const int MAXN=200+50; 8 vector<int> E[MAXN]; 9 vector<int> rE[MAXN]; 10 vector<int> vs; 11 int cmp[MAXN],vis[MAXN]; 12 int cnt,n,m; 13 14 void addedge(int u,int v) 15 { 16 E[u].push_back(v); 17 rE[v].push_back(u); 18 } 19 20 void dfs(int u) 21 { 22 vis[u]=1; 23 for (int i=0;i<E[u].size();i++) 24 { 25 int v=E[u][i]; 26 if (!vis[v]) dfs(v); 27 } 28 vs.push_back(u); 29 } 30 31 void rdfs(int u,int t) 32 { 33 vis[u]=1; 34 cmp[u]=t; 35 for (int i=0;i<rE[u].size();i++) 36 { 37 int v=rE[u][i]; 38 if (!vis[v]) rdfs(v,t); 39 } 40 } 41 42 void init() 43 { 44 for (int i=0;i<MAXN;i++) vector<int>().swap(E[i]); 45 for (int i=0;i<MAXN;i++) vector<int>().swap(rE[i]); 46 scanf("%d%d",&n,&m); 47 for (int i=0;i<m;i++) 48 { 49 char c1,c2; 50 int x,y,fx,fy; 51 getchar(); 52 scanf("%c%d %c%d",&c1,&x,&c2,&y); 53 if (c1=='m') fx=x+n;else fx=x; 54 if (c2=='m') fy=y+n;else fy=y; 55 if (c1=='h') addedge(x+n,fy);else if (c1=='m') addedge(x,fy); 56 if (c2=='h') addedge(y+n,fx);else if (c1=='m') addedge(y,fx); 57 } 58 } 59 60 void solve() 61 { 62 memset(vis,0,sizeof(vis)); 63 for (int i=1;i<=n;i++) if (!vis[i]) dfs(i); 64 memset(vis,0,sizeof(vis)),cnt=0; 65 for (int i=vs.size()-1;i>=0;i--) 66 if (!vis[vs[i]]) rdfs(vs[i],++cnt); 67 } 68 69 void get_ans() 70 { 71 for (int i=1;i<=n;i++) 72 if (cmp[i]==cmp[i+n]) 73 { 74 puts("BAD"); 75 return; 76 } 77 puts("GOOD"); 78 } 79 80 int main() 81 { 82 int T; 83 scanf("%d",&T); 84 while (T--) 85 { 86 init(); 87 solve(); 88 get_ans(); 89 } 90 return 0; 91 }