Gym 100917 F - Find the Length

来源:互联网 发布:房产网站源码 php 编辑:程序博客网 时间:2024/05/21 17:12
time limit per test
4 seconds (5 seconds for Java)
memory limit per test
256 megabytes
input
standard input
output
standard output

For each vertice of given undirected weighted graph calculate the length of shortest simple cycle, which contains this vertice.

Input

First line of the input contains one inteter n — number of vertices in the graph (1 ≤ n ≤ 300).

Each of n lines contain n integers, i-th integer in thei-th column is equal to 0 for anyi. If for i ≠ jj-th integer in i-th lineaij is equal to - 1, then vertices i andj are not connected, otherwise they are connected by the edge of weightaij (1 ≤ aij ≤ 106).

You may assume that graph does not contain self-loops and aij = aji for any1 ≤ i, j ≤ n.

Output

Print n integers one per line. i-th of those integers must be lentgh of the shortest simple cycle, containigi-th vertice. If no simple cycles containi-th vertiex, print  - 1 at corresponding line.

Examples
Input
40 9 1 19 0 -1 11 -1 0 -11 1 -1 0
Output
1111-111


分析:对于一个经过点i的最小环,它至少由三点组成,取一个由i点直接连出的点j,当j到i的最短路小于F[i][j]时,最小环就等于dis[j]+f[i][j];

当最短路d[j] >= F[i][j]时,我们一定可以找到另一个j点直接连出的点k(d[k]的路径不经过j点),此时最短路由dis[j]+F[j][k]+dis[k]组成。

可以证明这两种情况的并集一定包含了最小环。

#include <cstdio>#include <iostream>#include <cstring>#define MAXN 2147483647 using namespace std;long long n,f[301][301],fa[301],ans[301],z[30000],d[301];bool jud[301];int Find(int k){if(fa[k] == k) return k;fa[k]=Find(fa[k]);return fa[k];}int main(){cin>>n;for(int i=1;i <= n;i++) for(int j=1;j <= n;j++)  {  cin>>f[i][j];  if(f[i][j] <= 0) f[i][j]=MAXN;  }for(int now=1;now <= n;now++){for(int i=1;i <= n;i++) fa[i]=i;for(int i=1;i <= n;i++) d[i]=MAXN;memset(jud,0,sizeof(jud));d[now]=0,jud[now]=true;z[1]=now;int s=1,t=2;while(s != t){for(int i=1;i <= n;i++) if(f[z[s]][i]+d[z[s]] < d[i]) {  d[i]=f[z[s]][i]+d[z[s]];  if(z[s] != now) fa[i]=z[s];  if(!jud[i])  {  z[t]=i;  jud[i]=true;  t++;} }jud[z[s]]=false;s++;} ans[now]=MAXN;for(int i=1;i <= n;i++) if(Find(i) != i) ans[now]=min(ans[now],d[i]+f[now][i]);for(int i=1;i <= n;i++) for(int j=1;j <= n;j++)  if(i != now && j != now && Find(j) != Find(i))   ans[now]=min(ans[now],d[i]+f[i][j]+d[j]);}for(int i=1;i <= n;i++) if(ans[i] != MAXN) cout<<ans[i]<<endl;     else cout<<-1<<endl; } 



1 0
原创粉丝点击