HDU 1824 2-SAT
Let's go home
Problem Description
小时候,乡愁是一枚小小的邮票,我在这头,母亲在那头。
—— 余光中
集训是辛苦的,道路是坎坷的,休息还是必须的。经过一段时间的训练,lcy决定让大家回家放松一下,但是训练还是得照常进行,lcy想出了如下回家规定,每一个队(三人一队)或者队长留下或者其余两名队员同时留下;每一对队员,如果队员A留下,则队员B必须回家休息下,或者B留下,A回家。由于今年集训队人数突破往年同期最高记录,管理难度相当大,lcy也不知道自己的决定是否可行,所以这个难题就交给你了,呵呵,好处嘛~,免费**漂流一日。
—— 余光中
集训是辛苦的,道路是坎坷的,休息还是必须的。经过一段时间的训练,lcy决定让大家回家放松一下,但是训练还是得照常进行,lcy想出了如下回家规定,每一个队(三人一队)或者队长留下或者其余两名队员同时留下;每一对队员,如果队员A留下,则队员B必须回家休息下,或者B留下,A回家。由于今年集训队人数突破往年同期最高记录,管理难度相当大,lcy也不知道自己的决定是否可行,所以这个难题就交给你了,呵呵,好处嘛~,免费**漂流一日。
Input
第一行有两个整数,T和M,1<=T<=1000表示队伍数,1<=M<=5000表示对数。
接下来有T行,每行三个整数,表示一个队的队员编号,第一个队员就是该队队长。
然后有M行,每行两个整数,表示一对队员的编号。
每个队员只属于一个队。队员编号从0开始。
接下来有T行,每行三个整数,表示一个队的队员编号,第一个队员就是该队队长。
然后有M行,每行两个整数,表示一对队员的编号。
每个队员只属于一个队。队员编号从0开始。
Output
可行输出yes,否则输出no,以EOF为结束。
Sample Input
1 2 0 1 2 0 1 1 2 2 4 0 1 2 3 4 5 0 3 0 4 1 3 1 4
Sample Output
yes no
题意:不解释。
思路:根据题中所给冲突关系建图,tarjin缩点,判断存在有冲突关系的点是否在同一个连通分量里,假设存在,则方案不成立,否则成立。
代码:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<math.h>
#include<vector>
using namespace std;
struct node
{
int next,to;
}edge[5000000];
int head[50000],stk[1000000],belong[50000],dfn[50100],top,scc,indexx,T[50100],tol,low[50050];
bool instack[1010];
void add(int u,int v)
{
edge[tol].to=v;
edge[tol].next=head[u];
head[u]=tol++;
}
void tarjin(int u)
{
low[u]=dfn[u]=++indexx;
stk[top++]=u;
instack[u]=1;
int i,v;
for(i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if(!dfn[v])
{
tarjin(v);
if(low[u]>low[v])low[u]=low[v];
}
if(instack[v]&&low[u]>dfn[v])low[u]=dfn[v];
}
if(low[u]==dfn[u])
{
scc++;
do
{
v=stk[--top];
instack[v]=0;
belong[v]=scc;
}while(v!=u);
}
}
bool solve(int n)
{
memset(dfn,0,sizeof(dfn));
memset(instack,0,sizeof(instack));
indexx=top=scc=0;
int i,v,u;
for(i=0;i<6*n;i++)if(!dfn[i])tarjin(i);
}
int main()
{
int i,j,k,m,n,p,q;
while(~scanf("%d%d",&n,&m))
{
memset(head,-1,sizeof(head));
tol=0;
for(p=0;p<n;p++)
{
scanf("%d%d%d",&i,&j,&k);
add(2*i+1,2*j);
add(2*i+1,2*k);
add(2*j+1,2*i);
add(2*k+1,2*i);
}
while(m--)
{
scanf("%d%d",&i,&j);
add(2*i,2*j+1);
add(2*j,2*i+1);
}
solve(n);
bool flag=1;
for(i=0;i<n;i++)
if(belong[2*i]==belong[2*i+1])flag=0;
if(flag)puts("yes");else puts("no");
}
return 0;
}
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<math.h>
#include<vector>
using namespace std;
struct node
{
int next,to;
}edge[5000000];
int head[50000],stk[1000000],belong[50000],dfn[50100],top,scc,indexx,T[50100],tol,low[50050];
bool instack[1010];
void add(int u,int v)
{
edge[tol].to=v;
edge[tol].next=head[u];
head[u]=tol++;
}
void tarjin(int u)
{
low[u]=dfn[u]=++indexx;
stk[top++]=u;
instack[u]=1;
int i,v;
for(i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if(!dfn[v])
{
tarjin(v);
if(low[u]>low[v])low[u]=low[v];
}
if(instack[v]&&low[u]>dfn[v])low[u]=dfn[v];
}
if(low[u]==dfn[u])
{
scc++;
do
{
v=stk[--top];
instack[v]=0;
belong[v]=scc;
}while(v!=u);
}
}
bool solve(int n)
{
memset(dfn,0,sizeof(dfn));
memset(instack,0,sizeof(instack));
indexx=top=scc=0;
int i,v,u;
for(i=0;i<6*n;i++)if(!dfn[i])tarjin(i);
}
int main()
{
int i,j,k,m,n,p,q;
while(~scanf("%d%d",&n,&m))
{
memset(head,-1,sizeof(head));
tol=0;
for(p=0;p<n;p++)
{
scanf("%d%d%d",&i,&j,&k);
add(2*i+1,2*j);
add(2*i+1,2*k);
add(2*j+1,2*i);
add(2*k+1,2*i);
}
while(m--)
{
scanf("%d%d",&i,&j);
add(2*i,2*j+1);
add(2*j,2*i+1);
}
solve(n);
bool flag=1;
for(i=0;i<n;i++)
if(belong[2*i]==belong[2*i+1])flag=0;
if(flag)puts("yes");else puts("no");
}
return 0;
}

浙公网安备 33010602011771号