题目链接:https://vjudge.net/problem/UVA-11090
n个点m条边的加权有向图,求权值最小的回路。
看了白书才明白是二分寻找答案,让我自己想肯定想不到。每条边的权值减去mid值,判断是否形成负权回路即可。写了两种写法,不是很喜欢集合在结构体里面…不过封装确实简洁很多。第一种是队列,第二种直接循环。
今天下午队伍一起打了个训练赛,写去年乌鲁木齐的题目,签到完就写不了第三题了。。不过最近确实状态也不好,脑子也转不过来,顶多充当翻译员。希望去青岛的时候竞技状态能好一点,虽然是Latte队伍!
最后恭喜IG!
/*
* @Author: SamsonHo
* @Date: 2018-10-26-16.11.25
* @URL:https://vjudge.net/problem/UVA-11090
*/
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int MAXN = 1e4+10;
struct Edge
{
int from,to;
double val;
Edge(int from,int to,double val):from(from),to(to),val(val) {}
};
vector<Edge> edges;
vector<int> g[MAXN];
int n,m,cnt[MAXN],inque[MAXN];
double d[MAXN];
bool Bellman_Ford()
{
queue<int> que;
for(int i = 1; i <= n; ++i)
{
d[i] = 0;
cnt[i] = 0;
que.push(i);
}
inque[1] = 1;
while(!que.empty())
{
int u = que.front();
que.pop();
inque[u] = 0;
int len = g[u].size();
for(int i = 0; i < len; ++i)
{
Edge& e = edges[g[u][i]];
if(d[e.to] > d[e.from]+e.val)
{
d[e.to] = d[e.from]+e.val;
if(!inque[e.to])
{
que.push(e.to);
inque[e.to] = 1;
if(++cnt[e.to] > n) return true;
}
}
}
}
return false;
}
bool test(double x)
{
for(int i = 0; i < m; ++i)
edges[i].val -= x;
bool ret = Bellman_Ford();
for(int i = 0; i < m; ++i)
edges[i].val += x;
return ret;
}
int main(void)
{
int T,kase = 0;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i = 0; i <= n; ++i)
g[i].clear();
edges.clear();
int u,v,Max = 0;
double w;
for(int i = 0; i < m; ++i)
{
scanf("%d%d%lf",&u,&v,&w);
if(w > Max) Max = w;
edges.push_back(Edge(u,v,w));
g[u].push_back(i);
}
printf("Case #%d: ",++kase);
if(!test(Max+1))
puts("No cycle found.");
else
{
double l = 0,r = Max;
while(r - l > 1e-3)
{
double m = l+(r-l)/2.0;
if(test(m)) r = m;
else l = m;
}
printf("%.2lf\n",l);
}
}
}
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int MAXN = 1e4+10;
struct Edge
{
int from,to;
double val;
Edge(int from,int to,double val):from(from),to(to),val(val) {}
};
vector<Edge> edges;
vector<int> g[MAXN];
int n,m,cnt[MAXN],inque[MAXN],num;
double d[MAXN];
bool Bellman_Ford(int s)
{
for(int i = 0; i <= n; ++i) d[i] = INF;
d[s] = 0;
for(int i = 0; i < n-1; ++i)
{
for(int j = 0; j < m; ++j)
{
if(d[edges[j].to] > d[edges[j].from] + edges[j].val)
d[edges[j].to] = d[edges[j].from] + edges[j].val;
}
}
for(int i = 0; i < m; ++i)
{
if(d[edges[i].to] > d[edges[i].from] + edges[i].val)
return true;
}
return false;
}
bool test(double x)
{
for(int i = 0; i < m; ++i)
edges[i].val -= x;
bool ret = Bellman_Ford(1);
for(int i = 0; i < m; ++i)
edges[i].val += x;
return ret;
}
int main(void)
{
int T,kase = 0;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i = 0; i <= n; ++i)
g[i].clear();
edges.clear();
int u,v,Max = 0;
double w;
for(int i = 0; i < m; ++i)
{
scanf("%d%d%lf",&u,&v,&w);
if(w > Max) Max = w;
edges.push_back(Edge(u,v,w));
g[u].push_back(i);
}
printf("Case #%d: ",++kase);
if(!test(Max+1))
puts("No cycle found.");
else
{
double l = 0,r = Max;
while(r - l > 1e-3)
{
double m = l+(r-l)/2.0;
if(test(m)) r = m;
else l = m;
}
printf("%.2lf\n",l);
}
}
}