题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4598
思路:由题意可知两相连点ai符号一定相反,所以若存在奇圈则一定无解。染色,colour[i]==1表示为正,colour[i]==2表示为负。由于(b)条件为充要条件,所以对于图中的点| a[i]-a[j] | >= T,对于非图中点| a[i]-a[j] | < T,即| a[i]-a[j] | <= T-1 。所以图中点,若colour[i]==1,a[i]-a[j] >= T,否则a[j]-a[i] >= T。非图中点同理,差分约束建图后若图中存在负环则无解,否则有解。
#include<cstdio> #include<queue> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define debu using namespace std; const int T=1111; const int maxn=350; struct Node { int v,w; Node(int v=0,int w=0):v(v),w(w) {} }; int n; queue<int> q; vector<int> g[maxn]; char st[maxn][maxn]; int Map[maxn][maxn]; vector<Node> G[maxn]; int dist[maxn],v[maxn]; int colour[maxn],tot[maxn]; void Find(int x,int flag) { //cout<<x<<" "<<flag<<endl; colour[x]=flag; for(int i=0; i<g[x].size(); i++) if(!colour[g[x][i]]) Find(g[x][i],3-flag); } int check() { //cout<<"Flag"<<endl; memset(colour,0,sizeof(colour)); for(int i=1; i<=n; i++) if(!colour[i]) Find(i,1); //cout<<"Flag"<<endl; for(int i=1; i<=n; i++) for(int j=0; j<g[i].size(); j++) if(colour[i]==colour[g[i][j]]) return 0; return 1; } void make() { for(int i=0; i<=n; i++) G[i].clear(); for(int i=1; i<=n; i++) for(int j=i+1; j<=n; j++) { //cout<<st[i-1][j-1]<<" "<<colour[i]<<endl; if(st[i-1][j-1]=='1') { if(colour[i]==1) { //cout<<i<<" "<<j<<" "<<-T<<endl; G[i].push_back(Node(j,-T)); } else { //cout<<j<<" "<<i<<" "<<-T<<endl; G[j].push_back(Node(i,-T)); } } else { if(colour[i]==1) { //cout<<j<<" "<<i<<" "<<T-1<<endl; G[j].push_back(Node(i,T-1)); } else { //cout<<i<<" "<<j<<" "<<T-1<<endl; G[i].push_back(Node(j,T-1)); } } } /*for(int i=1; i<=n; i++) cout<<i<<" "<<colour[i]<<endl; for(int i=1; i<=n; i++) { cout<<G[i].size()<<endl; for(int j=0; j<G[i].size(); j++) cout<<i<<" "<<G[i][j].v<<" "<<G[i][j].w<<endl; }*/ } int solve() { make(); //cout<<"Flag"<<endl; while(!q.empty()) q.pop(); memset(tot,0,sizeof(tot)); memset(dist,0,sizeof(dist)); for(int i=1; i<=n; i++) { v[i]=1; q.push(i); } while(!q.empty()) { int now=q.front(); //cout<<now<<endl; q.pop(),v[now]=0; for(int i=0; i<G[now].size(); i++) { int nt=G[now][i].v; if(dist[nt]>dist[now]+G[now][i].w) { dist[nt]=dist[now]+G[now][i].w; if(!v[nt]); { v[nt]=1; q.push(nt); if(++tot[nt]>n) return 0; } } } } return 1; } int main() { #ifdef debug freopen("in.in","r",stdin); #endif // debug int t; scanf("%d",&t); while(t--) { scanf("%d",&n); getchar(); //memset(Map,0,sizeof(Map)); for(int i=0; i<=n; i++) g[i].clear(); for(int i=0; i<n; i++) { scanf("%s",st[i]); //cout<<st[i]<<endl; for(int j=0; j<n; j++) if(st[i][j]=='1') g[i+1].push_back(j+1); } if(check()&&solve()) printf("Yes\n"); else printf("No\n"); } return 0; }
Hdu 4594 Difference(奇圈判断+差分约束)
原文:http://blog.csdn.net/wang2147483647/article/details/52122864