URAL 1382 Game with Cards 解题报告
2013-07-07 17:10
316 查看
题目
比赛
题意:
有N张牌,N个人,每个人会说两句话,"我拿着牌a"和"b拿着牌c",这两句话中有且只有一句话是对的。
求每个人说的话中哪一句话是对的,题目保证一定有解
思路:
2-sat,对于第i个人,有第一句是对的I1,第二句话是对的I2两种互斥的状态,可以把I1看成"i拿着牌a",则当两句话中人相同牌不同时,或者人不同牌相同时,这两句话产生冲突,然后就套用2-sat输出解的模板。
代码:
比赛
题意:
有N张牌,N个人,每个人会说两句话,"我拿着牌a"和"b拿着牌c",这两句话中有且只有一句话是对的。
求每个人说的话中哪一句话是对的,题目保证一定有解
思路:
2-sat,对于第i个人,有第一句是对的I1,第二句话是对的I2两种互斥的状态,可以把I1看成"i拿着牌a",则当两句话中人相同牌不同时,或者人不同牌相同时,这两句话产生冲突,然后就套用2-sat输出解的模板。
代码:
#include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <queue> using namespace std; #define maxN 1005 #define maxn 2005 #define maxm 5000005 int n; struct node { int s,t; int next; }e[maxm],e2[maxm]; int ecnt,ecnt2,pre[maxn],pre2[maxn]; int a[maxn],b[maxn]; void addEdge(int u,int v) { e[ecnt].s=u; e[ecnt].t=v; e[ecnt].next=pre[u]; pre[u]=ecnt++; } void addE(int u,int v) { e2[ecnt2].s=u; e2[ecnt2].t=v; e2[ecnt2].next=pre2[u]; pre2[u]=ecnt2++; } int Dindex,top,cnt; int dfn[maxn],low[maxn],bel[maxn]; int stack[maxn]; bool instack[maxn]; void tarjan(int u) { int v; dfn[u]=low[u]=++Dindex; stack[++top]=u; instack[u]=true; for (int i=pre[u];i!=-1;i=e[i].next) { v=e[i].t; if (!dfn[v]) { tarjan(v); if (low[v]<low[u]) low[u]=low[v]; } else if (instack[v]&&dfn[v]<low[u]) low[u]=dfn[v]; } if (dfn[u]==low[u]) { cnt++; do { v=stack[top--]; instack[v]=false; bel[v]=cnt; }while (u!=v); } } void solve() { Dindex=top=cnt=0; for (int i=1;i<=2*n;i++) if (!dfn[i]) tarjan(i); } int cf[maxn],in[maxn],col[maxn]; bool ans[maxn]; void re_build() { ecnt2=0; memset(pre2,-1,sizeof(pre2)); for (int i=0;i<ecnt;i++) { if (bel[e[i].s]!=bel[e[i].t]) { addE(bel[e[i].t],bel[e[i].s]); in[bel[e[i].s]]++; } } } void topsort() { queue<int> q; for (int i=1;i<=cnt;i++) if (in[i]==0) q.push(i); while (!q.empty()) { int u=q.front(); q.pop(); if (col[u]==0) { col[u]=1; col[cf[u]]=-1; } for (int i=pre2[u];i!=-1;i=e2[i].next) { int v=e2[i].t; in[v]--; if (in[v]==0) q.push(v); } } } void make() { solve(); for (int i=1;i<=n;i++) { cf[bel[i]]=bel[i+n]; cf[bel[i+n]]=bel[i]; } re_build(); topsort(); for (int i=1;i<n;i++) if (col[bel[i]]==1) printf("1 "); else printf("2 "); if (col[bel ]==1) printf("1\n"); else printf("2\n"); } int main() { //freopen("/home/moor/Code/input.txt","r",stdin); scanf("%d",&n); int x,y,z; for (int i=1;i<=n;i++) { scanf("%d%d%d",&x,&y,&z); a[i]=i; b[i]=x; a[i+n]=y; b[i+n]=z; } ecnt=0; memset(pre,-1,sizeof(pre)); for (int i=1;i<=2*n;i++) for (int j=i+1;j<=2*n;j++) { if ((a[i]==a[j]&&b[i]!=b[j])||(a[i]!=a[j]&&b[i]==b[j])) { if (j<=n) addEdge(i,j+n); else addEdge(i,j-n); if (i<=n) addEdge(j,i+n); else addEdge(j,i-n); } } make(); return 0; }
相关文章推荐
- 解题报告:Codeforces Round #432 (Div. 2) E.Arpa and a game with Mojtaba (博弈)
- [leetcode] 174. Dungeon Game 解题报告
- codeforces 140B.New Year Cards 解题报告
- URAL 1699 Turning Turtles 解题报告
- 2014百度之星复赛解题报告:The Game of Coins
- 【解题报告】HDU 4616 Game - 树形dp
- HDOJ 1134 Game of Connections 简单解题报告
- LeetCode解题报告--Container With Most Water
- POJ 3468 A Simple Problem with Integers (线段树成段更新) 解题报告
- Copy List with Random Pointer的解题报告
- HDU 5828 Rikka with Sequence 解题报告
- Ural 1001 Reverse Root 解题报告
- LeetCode 292.Nim Game 解题报告
- [Leetcode] 340. Longest Substring with At Most K Distinct Characters 解题报告
- HDU 3071-Gcd & Lcm game-线段树+素因子分解-[解题报告]HOJ
- Guessing Game解题报告 (pku 2328)
- LeetCode — Copy List with Random Pointer 解题报告
- 2014百度之星复赛解题报告:The Game of Coins
- 【LeetCode】Jump Game II 解题报告
- Ural 1091 Tmutarakan Exams 解题报告(容斥原理)