http://acm.hdu.edu.cn/showproblem.php?pid=6141
比赛的时候根本没看那道题。
学习中。mark一下。
最小树形图 就是有向图的最小生成树。
一般用朱刘算法。
1 加入最小的边。如果存在孤立点,那么肯定不会有最小树形图。break
2 如果有 不包含root的环,对环进行缩点。
3 反复进行,直到没有环。
但这一道题还有不一样的地方,因为要求最大,所以全变成负数。
要 v-1这个点 的父节点尽可能小,所以 v-1的邻接边 全加上他的 父节点,
最后在后面的处理。。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <vector>
#include <queue>
#include <stack>
#include <deque>
#include <string>
#include <map>
#include <set>
using namespace std;
#define INF 0x3f3f3f3f
#define LL long long
#define fi first
#define se second
#define mem(a,b) memset((a),(b),sizeof(a))
const int MAXV=1000+3;//最大顶点数
const int MAXE=10000+3;//最大边数
struct Edge
{
int u, v;
int cost;
}edge[MAXE];//边集
int V,E;//顶点数,边数
int pre[MAXV],id[MAXV],vis[MAXV];
int in[MAXV];
int zhuliu(int root)//返回最小花费
{
int res=0;
while(true)
{
for(int i=0;i<V;++i)
in[i]=INF;
for(int i=0;i<E;++i)
if(edge[i].u!=edge[i].v&&edge[i].cost<in[edge[i].v])
{
pre[edge[i].v]=edge[i].u;
in[edge[i].v]=edge[i].cost;//在所有点中寻找最小的。标定他的 弧头
}
for(int i=0;i<V;++i)
if(i!=root&&in[i]==INF)
return -1;//不存在最小树形图,因为有一个 孤立的点,怎么连都连不到
int tn=0;//新图结点数
for(int i=0;i<V;++i)
{
id[i]=-1;
vis[i]=-1;
}
in[root]=0;
for(int i=0;i<V;++i)
{
res+=in[i];
int v=i;
while(vis[v]!=i&&id[v]==-1&&v!=root)
{
vis[v]=i;
v=pre[v];// 向后遍历。vis是记录的 那条链的尾
}
if(v!=root&&id[v]==-1)
{
for(int u=pre[v];u!=v;u=pre[u])
id[u]=tn;
id[v]=tn++;//求环、id是记录环的标号。缩点操作
}
}
if(tn==0)//没有有向环
break;
for(int i=0;i<V;++i)
if(id[i]==-1)
id[i]=tn++;// 自环
for(int i=0;i<E;i++)
{
int v=edge[i].v;
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[--E]);
}
V=tn;
root=id[root];
}
return res;
}
int main()
{
int T;
scanf("%d", &T);
while(T--){
scanf("%d%d",&V,&E);
for(int i=0;i<E;i++){
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].cost);
edge[i].u--,edge[i].v--;
edge[i].cost*=-1000;
if(edge[i].v==V-1)
edge[i].cost+=edge[i].u;
}
int ans=zhuliu(0);
printf("%d %d\n",(-ans+999)/1000,(-ans+999)/1000*1000+ans+1);//最后加1,因为过程中处理的是 0-v-1的,所以要加1变为原来的、
}
return 0;
}