POJ_3207题解

来源:互联网 发布:免费独立域名申请 编辑:程序博客网 时间:2024/06/10 08:32

输入:n  m    //n个点从0-(n-1)编号,顺时针放在一圆上,有m条边,每个点最多只与一条边相连。

以下m行输入m条边的两点。

边可以在圆内连接,也可以在圆外连接,问,是否可以连接着m条边,且没有交点。

很经典的2-SAT问题,将每条边视为点,在圆内连接则为i,在圆外连接则为i+m,若两条边 i,j 都在圆内连接会相交,则存在2-SAT的边:

i->j+m

j+m->i

j->i+m

i+m->j

然后求强连通块,若两点同时在同一强连通块里,则必无解,反之,有解。


//time:79ms#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<stack>#include<queue>#define BUG printf("here!~\n");using namespace std;int n,m;int ea[510],eb[510];vector<int> G[2010];stack<int> s;int pre[2010],scc[2010],low[2010];int cnt,num;void DFS(int u){pre[u]=low[u]=++num;s.push(u);int v;for(int i=0;i<G[u].size();++i) {v=G[u][i];if(!pre[v]) {DFS(v);low[u]=min(low[u],low[v]);}else if(!scc[v]) low[u]=min(low[u],pre[v]);}if(pre[u]==low[u]) {int tmp=-1;++cnt;while(tmp!=u) {tmp=s.top();s.pop();scc[tmp]=cnt;}}}void Tarjin(){cnt=0,num=0;for(int i=1;i<=n;++i)if(!pre[i])DFS(i);}int main(){int a,b,flag,aa,bb;scanf("%d%d",&n,&m);for(int i=1;i<=m;++i) {scanf("%d%d",ea+i,eb+i);for(int j=1;j<i;++j) {a=max(ea[j],eb[j]);b=min(ea[j],eb[j]);aa=max(ea[i],eb[i]);bb=min(ea[i],eb[i]);if((b<bb&&a>bb&&a<aa)||(a>aa&&b>bb&&b<aa)) {                G[i].push_back(j+m);                G[j+m].push_back(i);                G[j].push_back(i+m);                G[i+m].push_back(j);}}}n=m+m;Tarjin();flag=1;for(int i=1;i<=m;++i)if(scc[i]==scc[i+m]) {flag=0;break;}if(flag) printf("panda is telling the truth...\n");else printf("the evil panda is lying again\n");return 0;}


原创粉丝点击