Problem UVA - 11478 - Halum
Time Limit: 3000 mSec
Problem Description
You are given a directed graph G(V,E) with a set of vertices and edges. Each edge (i,j) that connects some vertex i to vertex j has an integer cost associated with that edge. Define the operation Halum(v,d) to operate on a vertex v using an integer d as follows: subtract d from the cost of all edges that enter v and add d to the cost of every edge that leaves v. As an example of that operation, consider graph G that has three vertices named (1, 2, 3) and two edges. Edge (1, 2) has cost -1, and edge (2,3) has cost 1. The operation Halum(2,−3) operates on edges entering and leaving vertex 2. Thus, edge (1, 2) gets cost -1-(-3)=2 and the edge (2, 3) gets cost 1 + (-3) = -2. Your goal is to apply the Halum function to a graph, potentially repeatedly, until every edge in the graph has at least a certain cost that is greater than zero. You have to maximize this cost.
Input
Two space-separated integers per case: V (V ≤ 500) and E (E ≤ 2700). E lines follow. Each line represents a directe
Output
If the problem is solvable, then print the maximum possible value. If there is no such solution print ‘No Solution’. If the value can be arbitrary large print ‘Infinite’
Sample Input
Sample Output
Infinite
Infinite
3
1
题解:二分+差分约束系统,解决方法很固定,跑个spfa判负环就能判断差分约束系统是否有解,这个题是让最小边权最大,所以显然二分,还加了一点说是要边权大于0,所以先判断最小边权是1行不行,不行的话显然就是无解得情况,再判断最小边权是所有边中最大的+1行不行,如果可以,说明根本就没有回路,这时最小权值想多大就多大(让入度为0的点增加INF),所以是无穷大的情况,除此之外就是二分了,没什么难度。还有个地方需要说明一下,从代码可以看出这和普通的spfa有一点区别就是没有源点,看似是个大问题,其实很容易理解,差分约束系统其实一般是要添加一个源点的,从源点到所有点的距离都是0,这里省略了加点,加边的操作,直接将第一次松弛后的状态作为初始状态,这显然是可以的,因为即便加边也是加的从源点到各个点的有向边,第一次松弛结束后不可能再通过源点松弛,所以直接省略源点即可。
#include <bits/stdc++.h> using namespace std; #define REP(i, n) for (int i = 1; i <= (n); i++)
#define sqr(x) ((x) * (x)) const int maxn = + ;
const int maxm = + ;
const int maxs = + ; typedef long long LL;
typedef pair<int, int> pii;
typedef pair<double, double> pdd; const LL unit = 1LL;
const int INF = 0x3f3f3f3f;
const LL mod = ;
const double eps = 1e-;
const double inf = 1e15;
const double pi = acos(-1.0); struct Edge
{
int to, next, w;
} edge[maxm]; int n, m, st;
int head[maxn], tot; void init()
{
memset(head, -, sizeof(head));
tot = ;
} void AddEdge(int u, int v, int w)
{
edge[tot].to = v;
edge[tot].w = w;
edge[tot].next = head[u];
head[u] = tot++;
} int dist[maxn], cnt[maxn];
bool vis[maxn]; bool spfa()
{
queue<int> que;
memset(cnt, , sizeof(cnt));
for(int i = ; i < n; i++)
{
que.push(i);
dist[i] = ;
vis[i] = true;
}
while (!que.empty())
{
int u = que.front();
que.pop();
vis[u] = false;
for (int i = head[u]; i != -; i = edge[i].next)
{
int v = edge[i].to;
if (dist[v] > dist[u] + edge[i].w)
{
dist[v] = dist[u] + edge[i].w;
if (!vis[v])
{
vis[v] = true;
que.push(v);
if (++cnt[v] > n)
{
return false;
}
}
}
}
}
return true;
} bool Judge(int lim)
{
for (int i = ; i < m; i++)
{
edge[i].w -= lim;
}
bool ok = spfa();
for (int i = ; i < m; i++)
{
edge[i].w += lim;
}
return ok;
} int main()
{
ios::sync_with_stdio(false);
cin.tie();
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
while (cin >> n >> m)
{
init();
int u, v, d;
int le = , ri = ;
for (int i = ; i < m; i++)
{
cin >> u >> v >> d;
u--, v--;
AddEdge(u, v, d);
ri = max(ri, d);
} if(!Judge(le))
{
cout << "No Solution" << endl;
continue;
}
else if(Judge(ri + ))
{
cout << "Infinite" << endl;
continue;
} int ans = -INF;
while (le <= ri)
{
int mid = (le + ri) / ;
if (Judge(mid))
{
le = mid + ;
ans = mid;
}
else
{
ri = mid - ;
}
}
cout << ans << endl;
}
return ;
}