BZOJ4349 最小树形图

【最开始想错了 以为必须全打掉才可以用后来的新代价 WA飞以后看题解才明白qaq

//Love and Freedom.
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf 1e20
#define ll long long
#define N 1100
#define M 100100
#define db double
using namespace std;

struct edge{int u,v; db c;}e[M];
int pre[N],id[N],vis[N];
int n,m;db mn[N];
db zlal(int rt)
{
db res = 0.0;
while(1)
{
for(int i=1;i<=n;i++)    mn[i] = inf;
for(int i=1;i<=m;i++)
if(e[i].u != e[i].v && mn[e[i].v]>e[i].c)
{
mn[e[i].v] = e[i].c; pre[e[i].v] = e[i].u;
}
for(int i=1;i<=n;i++)    if(i!=rt && mn[i]==inf)    return 0;
int tn = 0,u,v;
memset(id,0,sizeof(id)); memset(vis,0,sizeof(vis));
mn[rt] = 0;
for(int i=1;i<=n;i++)
{
res += mn[i]; v=i;
while(v!=rt && !id[v] && vis[v]!=i)
vis[v] = i, v = pre[v];
if(v!=rt && !id[v])
{
++tn;
for(u=pre[v];u!=v;u=pre[u])
id[u] = tn;
id[v] = tn;
}
}
if(!tn)    break;
for(int i=1;i<=n;i++)    if(!id[i])
id[i] = ++tn;
for(int i=1;i<=m;i++)
{
v = e[i].v;
e[i].u = id[e[i].u];
e[i].v = id[e[i].v];
if(e[i].u != e[i].v)
e[i].c -= mn[v];
}
n = tn; rt = id[rt];
}
return res;
}
db a[N],cc[N]; int b[N],cnt;
int main()
{
//int r;    scanf("%d%d%d",&n,&m,&r);
//for(int i=1;i<=m;i++)    scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].c);
scanf("%d",&n); n++; db ans = 0.0;
for(int i=1;i<n;i++)
{
scanf("%lf%d",&a[i],&b[i]);
if(b[i]<=0)    continue;// ans+=(b[i]-1)*a[i];
e[++cnt].u = n, e[cnt].v=i ,cc[i]=e[cnt].c=a[i];
}
int k,x,y;db c; scanf("%d",&k);
for(int i=1;i<=k;i++)
{
scanf("%d%d%lf",&x,&y,&c);
e[++cnt].u=x; e[cnt].v=y; e[cnt].c=c; cc[y]=min(cc[y],c);
} m = cnt;
for(int i=1;i<n;i++)    ans+=(b[i]-1)*cc[i];
printf("%.2lf\n",zlal(n) +ans);
return 0;
}
/**
3
10.00 1
1.80 1
2.50 2
2
1 3 2.00
3 2 1.50
*/
View Code

posted @ 2019-02-12 18:53  寒雨微凝  阅读(117)  评论(0编辑  收藏  举报