您的位置:首页 > 编程语言 > Go语言

hdu 3715 Go Deeper 2 - sat

2011-07-24 09:52 417 查看
去年成都现场赛的题!!

再次强调一下,2-sat箴言:如果a与b矛盾,则建边(a,b');

到n-1表示0,n到2*n-1表示1

if(C[i]==0) add(x,y+n);add(y,x+n);

if(C[i]==1) add(x,y);add(y,x);add(x+n,y+n);add(y+n,x+n);
if(C[i]==2) add(x+n,y);add(y+n,x);

二分枚举可以到的最大dep值,然后建边用2-sat判断是否可行。

贴下我的代码:

View Code

# include<stdio.h>
# include<string.h>
# define M 80005
# define N 500
struct node{
int from,to,next;
}edge1[M],edge2[M];
struct node1{
int a,b,c;
}s[M];
int n,m,head1
,head2
,visit1
,visit2
,tol1,tol2,Tcnt,Bcnt,T
,Belong
;
void add(int a,int b)
{
edge1[tol1].from=a;edge1[tol1].to=b;edge1[tol1].next=head1[a];head1[a]=tol1++;
edge2[tol2].from=b;edge2[tol2].to=a;edge2[tol2].next=head2[b];head2[b]=tol2++;
}
void dfs1(int i)
{
int j,u;
visit1[i]=1;
for(j=head1[i];j!=-1;j=edge1[j].next)
{
u=edge1[j].to;
if(!visit1[u]) dfs1(u);
}
T[Tcnt++]=i;
}
void dfs2(int i)
{
int j,u;
visit2[i]=1;
Belong[i]=Bcnt;
for(j=head2[i];j!=-1;j=edge2[j].next)
{
u=edge2[j].to;
if(!visit2[u]) dfs2(u);
}
}
int main()
{
int i,ans,right,left,mid,ncase;
scanf("%d",&ncase);
while(ncase--)
{
scanf("%d%d",&n,&m);
for(i=0;i<m;i++)
scanf("%d%d%d",&s[i].a,&s[i].b,&s[i].c);
left=0;
right=m;
while(left<=right)
{
mid=(left+right)/2;
memset(head1,-1,sizeof(head1));
memset(head2,-1,sizeof(head2));
memset(visit1,0,sizeof(visit1));
memset(visit2,0,sizeof(visit2));
tol1=tol2=0;
Tcnt=Bcnt=0;
for(i=0;i<mid;i++)
{
if(s[i].c==0)
{
add(s[i].a,s[i].b+n);
add(s[i].b,s[i].a+n);
}
else if(s[i].c==1)
{
add(s[i].a,s[i].b);
add(s[i].b,s[i].a);
add(s[i].a+n,s[i].b+n);
add(s[i].b+n,s[i].a+n);
}
else if(s[i].c==2)
{
add(s[i].a+n,s[i].b);
add(s[i].b+n,s[i].a);
/*add(s[i].a,s[i].b+n);
add(s[i].b,s[i].a+n);*///这样写就wa了
}
}
for(i=0;i<2*n;i++)
if(!visit1[i]) dfs1(i);
for(i=Tcnt-1;i>=0;i--)
{
if(!visit2[T[i]])
{
dfs2(T[i]);
Bcnt++;
}
}
for(i=0;i<n;i++)
{
if(Belong[i]==Belong[i+n]) break;
}
if(i==n) {ans=mid;left=mid+1;}
else right=mid-1;
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: