uva 11478(二分+差分约束系统)

题意:这道题一开始题目看错了,结果浪费了一上午。这道题是对于每个点可以进行一种操作:所有以v为终点的边权值减小d,所有以v为起点的点权值增加d。最后要让所有边的权值非负(零也不行!!我就坑在这里)且尽量大。

思路:

解法一:先说一种不标准的解法,稍微思考一下可以发现经过若干次操作后会限制权值的主要是在环上的边。所以我们只要二分答案+SPFA判负环就能得出答案。

解法二:接下来说标准解法差分约束系统。由于在一个点上的多次操作是可以合并的,我们可以设sum[i]表示在i上操作的值。这样整个图就构成了若干个不等式sum[b]-sum[a]<=w[a][b]-x,由于图中不一定是强连通的所以我们需要再加一个顶点只想所有点边权为0。接下来二分答案执行SPFA判负环即可。

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <queue>
 8 #include <stack>
 9 #include <vector>
10 #define MP(a, b) make_pair(a, b)
11 #define PB(a) push_back(a)
12 
13 using namespace std;
14 
15 typedef long long ll;
16 typedef pair<int ,int> pii;
17 typedef pair<int, unsigned int> piu;
18 typedef pair<int ,double> pid;
19 typedef pair<ll, int> pli;
20 typedef pair<ll, ll> pll;
21 
22 const int INF = 0x3f3f3f3f;
23 const double eps = 1e-6;
24 const int LEN = 510;
25 
26 vector<pii> Map[LEN];
27 int n, m, l, r, dis[LEN];
28 
29 bool SPFA(int s, int val){
30     deque<int> q;
31     int vis[LEN] = {0}, cnt[LEN] = {0};
32     memset(dis, 0x3f, sizeof dis);
33     vis[s] = cnt[s] = 1;
34     dis[s] = 0;
35     q.push_back(s);
36     while(!q.empty())
37     {
38         int nv = q.front(); q.pop_front();vis[nv] = 0;
39         for(int i=0; i<Map[nv].size(); i++){
40             int x = Map[nv][i].first, y = Map[nv][i].second-val;
41             if(dis[x]>dis[nv]+y){
42                 dis[x] = dis[nv]+y;
43                 if(!vis[x]){
44                     vis[x] = 1;
45                     if(!q.empty()){
46                         if(dis[x]<dis[q.front()]) q.push_front(x);
47                         else q.push_back(x);
48                     }else
49                         q.push_back(x);
50                     cnt[x]++;
51                     if(cnt[x]>n)return true;
52                 }
53             }
54         }
55     }
56     return false;
57 }
58 
59 inline void read(int &ret)
60 {
61     char c;
62     while((c = getchar())<'0' || c>'9');
63     ret = 0;
64     while(c>='0' && c<='9'){
65         ret = ret*10+(c-'0');
66         c = getchar();
67     }
68 }
69 
70 int main()
71 {
72 //    freopen("in.txt", "r", stdin);
73 
74     while(scanf("%d%d", &n, &m)!=EOF){
75         for(int i=0; i<=n; i++) Map[i].clear();
76         l = 1, r = -INF;
77         for(int i=0; i<m ;i++){
78             int a, b, c;
79             read(a);read(b);scanf("%d", &c);
80             Map[a].PB(MP(b, c));
81             r = max(r, c);
82         }
83         for(int i=1; i<=n; i++)Map[0].PB(MP(i,0));
84         int ans;
85         if(SPFA(0, 1))puts("No Solution");
86         else if(!SPFA(0, r+1))puts("Infinite");
87         else {
88             while(l<r){
89                 int mid = (l+r+1)/2;
90                 if(SPFA(0, mid))r = mid-1;
91                 else l = mid;
92             }
93             printf("%d\n", l);
94         }
95     }
96     return 0;
97 }
View Code

 

posted @ 2014-01-03 10:18  张小豪  阅读(562)  评论(2编辑  收藏  举报