After awarded lands to ACMers, the queen want to choose a city be her capital. This is an important event in ice_cream world, and it also a very difficult problem, because the world have N cities and M roads, every road was directed. Wiskey is a chief engineer in ice_cream world. The queen asked Wiskey must find a suitable location to establish the capital, beautify the roads which let capital can visit each city and the project’s cost as less as better. If Wiskey can’t fulfill the queen’s require, he will be punishing.
Input
Every case have two integers N and M (N<=1000, M<=10000), the cities numbered 0…N-1, following M lines, each line contain three integers S, T and C, meaning from S to T have a road will cost C.
Output
If no location satisfy the queen’s require, you must be output “impossible”, otherwise, print the minimum cost in this project and suitable city’s number. May be exist many suitable cities, choose the minimum number city. After every case print one blank.
Sample Input
3 1
0 1 1
4 4
0 1 10
0 2 10
1 3 20
2 3 30
Sample Output
impossible
40 0
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 10005;
struct nede
{
int u;
int v;
int cost;
} Edge[maxn*maxn+10];
int pre[maxn], visit[maxn], id[maxn];
int in[maxn];
int edge_point, edge_w;
int zhuliu(int root, int n, int m)
{
int res = 0;
int v;
while(1)
{
for(int i=0; i<n; i++)//到达当前点的最小权值,先初始化
in[i] = INF;
for(int i=0; i<m; i++)//遍历每一个边
{
if(Edge[i].u!=Edge[i].v&&Edge[i].cost<in[Edge[i].v])//如果是一个边并且权值小于到达当前点的权值,更新
{
pre[Edge[i].v] = Edge[i].u;//pre记录前一个点,也就是从哪一点到达当前点
in[Edge[i].v] = Edge[i].cost;//更新权值
if(Edge[i].u==root)//更新超级点
edge_point = i;
}
}
for(int i=0; i<n; i++)//遍历每一个节点
{
if(i!=root&&in[i]==INF)//如果当前点不是根节点,但入度值最小为INF,也就是没有任何边指向此点,那么就不存在最小树形图
return -1;//返回-1
}
memset(id, -1, sizeof(id));//记录环的标号
memset(visit, -1, sizeof(visit));//是否访问过
int tn = 0;//环数
in[root] = 0;//根节点清零
for(int i=0; i<n; i++)//遍历每个节点,求最短弧的集合
{
res += in[i];//加入权值
int v = i;
while(visit[v]!=i&&id[v]==-1&&v!=root)//如果当前点没有被访问过,并且不是根节点,并且不在任何一个环上
{
visit[v] = i;
v = pre[v];
}
if(id[v]==-1&&v!=root)
{
for(int u=pre[v]; u!=v; u=pre[u])
{
id[u] = tn;
}
id[v] = tn++;
}
}
if(tn==0)//没有环出现,则找到了最小树形图
break;//跳出
for(int i=0; i<n; i++)//收缩有向环
{
if(id[i]==-1)
{
id[i] = tn++;
}
}
for(int i=0; i<m;i++)
{
v = Edge[i].v;
// int u = Edge[i].u;
Edge[i].u = id[Edge[i].u];
Edge[i].v = id[Edge[i].v];
if(Edge[i].u!=Edge[i].v)
Edge[i].cost -= in[v];
// else
// swap(Edge[i], Edge[--m]);
}
n = tn;
root = id[root];
}
return res;
}
int main()
{
int n, m;
while(~scanf("%d %d", &n, &m))
{
edge_w = 0;//计算权值
for(int i=0; i<m; i++)
{
int u, v, cost;
scanf("%d %d %d", &u, &v, &cost);
u++;//从1开始
v++;
Edge[i].u = u;
Edge[i].v = v;
if(u!=v)
Edge[i].cost = cost;
else
Edge[i].cost = INF;
edge_w += cost;
}
edge_w++;//权值+1,是为了成为最大权值的一条边
for(int i=0; i<n; i++)//创建一个虚拟点,然后到每个点的权值为最大值
{
Edge[i+m].u = 0;
Edge[i+m].v = i+1;
Edge[i+m].cost = edge_w;
}
int res = zhuliu(0, n+1, m+n);//找最小树形图
if(res==-1||res-edge_w>=edge_w)//如果权值-1或者太大了,则不可能
printf("impossible\n\n");
else
printf("%d %d\n\n", res-edge_w, edge_point-m);
}
return 0;
}