POJ_3207

http://poj.org/problem?id=3207

/*2-sat问题 2-SAT问题,通俗的说就是有n对点(2n个点),从每对点中选出一个点,共选出n个点, 而且要满足若干个这样的条件:某两点不能同时被选出。 设一对点为x、~x,如果a被选出则b一定要被选出,就在图中加有向弧(a,b)表示这种关系。 那么如果a,b(a!=b,a!=~b)不能同时被选出,那么加两条有向弧(a,~b),(b,~a)。 这样由图的对称性可以证明,2-SAT有解等价于任取x、~x,x、~x不在一个强联通分量中。 题意就是:平面上,一个圆,圆的边上按顺时针放着n个点。现在要连m条边,比如a,b, 那么a到b可以从圆的内部连接,也可以从圆的外部连接。给你的信息中,每个点最多只会连接的一条边。 问能不能连接这m条边,使这些边都不相交。 1:每个边看成2个点:分别表示在内部连接和在外部连接,只能选择一个。计作点i和点i' 2:如果两条边i和j必须一个画在内部,一个画在外部(一个简单判断就可以) 那么连边: i->j’, 表示i画内部的话,j只能画外部,即j’ j->i’,同理 i’->j,同理 j’->i,同理 然后就是2-sat算法了,tarjan一下,如果有i和i'同属于一个强联通,返回false,否则就成立 */ #include<iostream> #include<cmath> using namespace std; #define size 1100 int n, m, a, b, v[size], cnt, ee[size][2]; struct edge{int to, next;} e[500000]; void insert(int from, int to) { e[cnt].to = to; e[cnt].next = v[from];//每次都插入到最前面 v[from] = cnt++; } int belong[size], num[size], cntnum; int dfn[size], low[size], index, instack[size], sta[size], top; void tarjan(int id) { dfn[id] = low[id] = ++index; instack[id] = 1; sta[top++] = id; int tmp = v[id]; while(tmp != -1) { if (!dfn[e[tmp].to]) { tarjan(e[tmp].to); if (low[e[tmp].to] < low[id]) low[id] = low[e[tmp].to]; } else if (instack[e[tmp].to] && dfn[e[tmp].to] < low[id]) low[id] = dfn[e[tmp].to]; tmp = e[tmp].next; } if (dfn[id] == low[id]) { do { tmp = sta[--top]; instack[tmp] = 0; belong[tmp] = cntnum; num[cntnum]++; }while(tmp != id); cntnum++; } } int main() { // freopen("in.txt", "r", stdin); scanf("%d%d", &n, &m); memset(v, -1, sizeof(v)); cnt = 0; for(int i = 0; i < m ;i++) { scanf("%d%d", &ee[i][0], &ee[i][1]); if (ee[i][0] > ee[i][1]) swap(ee[i][0], ee[i][1]); } for(int i = 0; i < m; i++) for(int j = i + 1; j < m; j++) { if (ee[i][0] < ee[j][1] && ee[i][0] > ee[j][0] && ee[i][1] > ee[j][1] || ee[i][1] < ee[j][1] && ee[i][1] > ee[j][0] && ee[i][0] < ee[j][0]) { insert(i, j + m); insert(j, i + m); insert(j + m, i); insert(i + m, j); } } index = top = cntnum = 0; memset(num, 0, sizeof(num)); memset(dfn, 0, sizeof(dfn)); for(int i = 0; i < 2 * m; i++) if (!dfn[i]) tarjan(i); bool flag = true; for(int i = 0; i < m; i++) if (belong[i] == belong[i + m]) { flag = false; break; } if (flag) printf("panda is telling the truth.../n"); else printf("the evil panda is lying again/n"); return 0; }

你可能感兴趣的:(算法,struct,insert)