Description
给出一个
n
个点
Input
第一行一整数
Output
对于每组用例,输出最大费用有向树的权值和和 n 节点的父亲节点编号
Sample Input
2
3 3
1 2 10
1 3 10
2 3 10
3 3
1 2 10
1 3 10
2 3 11
Sample Output
20 1
21 2
Solution
模版题,通过改变边权使得
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define maxn 1111
struct Edge
{
int u,v,c;
}edge[10*maxn];
int pre[maxn],id[maxn],vis[maxn],in[maxn];
int zhuliu(int root,int n,int m)
{
int ans=0,u,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].c<in[edge[i].v])
{
pre[edge[i].v]=edge[i].u;
in[edge[i].v]=edge[i].c;
}
for(int i=0;i<n;i++)
if(i!=root&&in[i]==INF)
return -1;
int res=0;
memset(vis,-1,sizeof(vis));
memset(id,-1,sizeof(id));
in[root]=0;
for(int i=0;i<n;i++)
{
ans+=in[i];
v=i;
while(vis[v]!=i&&id[v]==-1&&v!=root)
{
vis[v]=i;
v=pre[v];
}
if(id[v]==-1&&v!=root)
{
for(u=pre[v];u!=v;u=pre[u])
id[u]=res;
id[v]=res++;
}
}
if(res==0)break;
for(int i=0;i<n;i++)
if(id[i]==-1)
id[i]=res++;
for(int i=0;i<m;i++)
{
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].c-=in[v];
}
n=res;
root=id[root];
}
return ans;
}
int T,n,m;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].c);
edge[i].u--,edge[i].v--,edge[i].c*=-n;
if(edge[i].v==n-1)edge[i].c+=edge[i].u;
}
int ans=-zhuliu(0,n,m);
printf("%d %d\n",(ans+n-1)/n,(ans+n-1)/n*n-ans+1);
}
return 0;
}