hdu 4598 Difference(spfa+差分约束,4级)

Difference

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 236    Accepted Submission(s): 67


Problem Description
A graph is a difference if every vertex vi can be assigned a real number ai and there exists a positive real number T such that
(a) |ai| < T for all i and 
(b) (vi, vj) in E <=> |ai - aj| >= T,
where E is the set of the edges. 
Now given a graph, please recognize it whether it is a difference.
 

Input
The first line of input contains one integer TC(1<=TC<=25), the number of test cases.
Then TC test cases follow. For each test case, the first line contains one integer N(1<=N<=300), the number of vertexes in the graph. Then N lines follow, each of the N line contains a string of length N. The j-th character in the i-th line is "1" if (vi, vj) in E, and it is "0" otherwise. The i-th character in the i-th line will be always "0". It is guaranteed that the j-th character in the i-th line will be the same as the i-th character in the j-th line.
 

Output
For each test case, output a string in one line. Output "Yes" if the graph is a difference, and "No" if it is not a difference.
 

Sample Input
3 4 0011 0001 1000 1100 4 0111 1001 1001 1110 3 000 000 000
 

Sample Output
Yes No Yes
Hint
In sample 1, it can let T=3 and a[sub]1[/sub]=-2, a[sub]2[/sub]=-1, a[sub]3[/sub]=1, a[sub]4[/sub]=2.
 

Source
 

Recommend
liuyidin
上学期的通化现场赛没A的差分约束,今天终于知道咋解了,其实也不难嘛!

思路:先判二分图,标记,然后任意选某种标记为正节点,我选颜色0,有边的需要满足 正节点-负节点>=T 无边的满足正节点-负节点<T 对于|V|<T建个虚节点

           此节点权为0,0<=正节点 -0<T  0<=0-负节点<T

建图,轻松搞定。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define clr(f,z) memset(f,z,sizeof(f))
using namespace std;
const int mm=330;
const int T=330;
bool vis[mm][mm],has[mm];
int id[mm];
int g[mm][mm];
int dis[mm];
int col[mm];
int n;
bool get()
{
  char z;
  while(1)
  {
    z=getchar();
    if(z=='1')return 1;
    if(z=='0')return 0;
  }
}
void paint(int u,bool cor)
{
  if(col[u]!=-1)return;
  col[u]=cor;
  FOR(i,1,n)
  if(vis[u][i])
  paint(i,cor^1);
}
bool spfa(int u)
{ int v;
  clr(dis,0x3f);clr(has,0);clr(id,0);
  dis[u]=0;has[u]=1;id[u]++;
  queue<int>Q;Q.push(u);
  while(!Q.empty())
  {
    u=Q.front();Q.pop();has[u]=0;
    for(int i=0;i<=n;++i)
    {
      if(dis[i]>dis[u]+g[u][i])
      {
        dis[i]=dis[u]+g[u][i];
        if(!has[i])
        {
         has[i]=1;Q.push(i);id[i]++;
         if(id[i]>n)return 0;
        }
      }
    }
  }
  return 1;
}
bool judge()
{
  clr(col,-1);
  FOR(i,1,n)paint(i,0);
  FOR(i,1,n)FOR(j,1,n)
  if(vis[i][j]&&col[i]==col[j])return 0;
  clr(g,0x3f);
  FOR(i,1,n)FOR(j,1,n)//0为正点 有边的 u->v>=T
  {
    if(vis[i][j])
    {
      if(col[i])g[i][j]=-T;///i-j<=-T
      else g[j][i]=-T;///j-i<=-T;
    }
    else
    {
      if(col[i])g[j][i]=T-1;///j-i<T
      else g[i][j]=T-1;///i-j<T
    }
  }
  ///0 虚节点
  FOR(i,1,n)
  {
    if(col[i])g[0][i]=T-1,g[i][0]=0;///0-i<T i-0>=0
    else g[i][0]=T-1,g[0][i]=0;
  }
  return spfa(0);
}
int main()
{
  int cas;
  while(~scanf("%d",&cas))
  {
    while(cas--)
    {
      scanf("%d",&n);
      FOR(i,1,n)FOR(j,1,n)
      vis[i][j]=get();
      if(judge())
        printf("Yes\n");
      else printf("No\n");
    }
  }
}





posted @ 2013-09-10 19:55  剑不飞  阅读(203)  评论(0编辑  收藏  举报