hdu 4598 Difference

为了做着道题,下午又找了几道差分约束的题做了,因为差分约束是很久以前看的,没怎么理解,现在看看,感觉理解的还不错了!

题意:判断是否存在图,使得像连的两个定点的值的差的绝对值大于等于T,并且每个定点的值都是小于T的

大致思路:比赛的时候就想到求奇圈了,但是一直wa,还很不理解,以为是代码写错了,后来想到,题中说的是相连的边的要求,那么也就要求了不想连的边的绝对值小于T了,而只求奇圈没有 满足这个的,于是现在又写了差分约束。。。

首先是建图,根据当时判断是否存在奇圈的时候将每个点是为正值或者是负值进行标记,然后就是对于相连的边i为正值的时候建立i->j =-T,i为负值的时候建立j->i =-T,不相连的边i为正值j->i=T-1,负值时为i->j =T-1,下面就直接用模板了!!!!

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<climits>
#include<map>
using namespace std;

#define rep(i,n) for(int i=0; i<n; i++)
#define repf(i,n,m) for(int i=(n); i<=(m); ++i)
#define repd(i,n,m) for(int i=(n); i>=(m); --i) 
#define ll long long
#define arc(a) ((a)*(a))
#define inf 10000000
#define exp 0.000001
#define N 305
#define T 400
int cont[N];
struct node
{
	int y,w,pre;
};
node a[N*N];
int pre[N];
int color[N];
bool vis[N];
int dp[N];
char s[N][N];
int n,len;

bool dfs(int x)
{
    color[x]=0;
	queue<int>q; q.push(x);
	while(!q.empty())
	{
		int x=q.front(); q.pop();
		rep(i,n)
			if(s[x][i]=='1')
				if(color[i]==-1)
					color[i]=color[x]^1,q.push(i);
				else if(color[i]==color[x])
					return false;
	}
	return true;
}

void init()
{
	memset(color,-1,sizeof(color));
	len=1;
	memset(pre,-1,sizeof(pre));
	rep(i,n) dp[i]=inf;
	memset(cont,0,sizeof(cont));
	memset(vis,false,sizeof(vis));
}
void addpage(int s,int t,int w)
{
	a[len].y=t;
	a[len].w=w;
	a[len].pre=pre[s];
	pre[s]=len++;
}
bool spfa()
{
     queue<int>q;
	 q.push(0);
	 vis[0]=true; dp[0]=0;
	 while(!q.empty())
	 {
		 int x=q.front(); q.pop(); vis[x]=false;
		 for(int i=pre[x]; i!=-1; i=a[i].pre)
		 {
			 int y=a[i].y;
			 if(dp[x]+a[i].w<dp[y])
			 {
				 dp[y]=dp[x]+a[i].w;
				 if(vis[y]==false)
				 {
					 q.push(y);
					 vis[y]=true;
					 cont[y]++;
					 if(cont[y]>n)
						 return false;
				 }
			 }
		 }
	 }
	 return true;
}
bool solve()
{
	init();
	rep(i,n)//jiquan de 
		if(color[i]==-1) 
			if(!dfs(i))
				return false;
	// bulid graph
	rep(i,n)
		repf(j,i+1,n-1)
		{
			if(s[i][j]=='0')
				if(color[i]==0)//zheng
                    addpage(j,i,T-1);
				else
					addpage(i,j,T-1);
			else
				if(color[i]==0)
					addpage(i,j,-T);
				else addpage(j,i,-T);
		}
	return spfa();
}

int main()
{ 
   int test;
   scanf("%d",&test);
   while(test--)
   {
	   scanf("%d",&n);
	   rep(i,n) scanf("%s",s[i]);
       if(solve())
		   printf("Yes\n");
	   else 
		   printf("No\n");
   }
   return 0;
}
  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淡定的小Y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值