CH Round #40 - Fimbulvetr::Prologue

题目:http://ch.ezoj.tk/contest/CH%20Round%20%2340%20-%20Fimbulvetr%3A%3APrologue/起源

题意:树上最大流+费用流,源点为树根,汇点为叶节点。

题解:

最大流貌似很好求?

这样搞

void dp(int x)
{
    f[x]=0;
    for(int i=head[x],y;i;i=e[i].next)
    {
        y=e[i].go;
        dp(y);
        f[x]+=min(e[i].v,f[y]);
    }
    if(!head[x])f[x]=inf;
}

然后 f[root]就是答案。

然后最小费用怎么搞呢?因为汇点是叶节点,所以一个叶节点到根的费用代表着一次增广,那我们如何分配流量,使得费用最小呢?

贪心!把每个叶节点的费用算出来,然后排序,从小的开始选,流量为它到根的流量的min,然后这条路上的流量都减去min,更新ans,

取min和修改 树剖即可,对LCT还不熟悉,不敢写。

然后继续选择后面的节点,直到流量分配完毕。

考场上由于一个return 少写了,然后1h写出来但没有调出来,感觉十分桑心,不过考后交了1A也算是对我的一种补偿。

代码:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<iostream>
  7 #include<vector>
  8 #include<map>
  9 #include<set>
 10 #include<queue>
 11 #include<string>
 12 #define inf 1000000000
 13 #define maxn 100000+10000
 14 #define maxm 500+100
 15 #define eps 1e-10
 16 #define ll long long
 17 #define pa pair<int,int>
 18 #define for0(i,n) for(int i=0;i<=(n);i++)
 19 #define for1(i,n) for(int i=1;i<=(n);i++)
 20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 21 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 22 #define mod 1000000007
 23 using namespace std;
 24 inline int read()
 25 {
 26     int x=0,f=1;char ch=getchar();
 27     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 28     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 29     return x*f;
 30 }
 31 struct edge{int go,next,v,c;}e[2*maxn];
 32 struct seg{int l,r,tag,mi;}t[4*maxn];
 33 struct rec{int x,y;}a[maxn];
 34 int n,tot,root,cnt=0,top[maxn],b[maxn],p[maxn],v[maxn];
 35 int fa[maxn],dep[maxn],head[maxn],son[maxn],s[maxn],f[maxn],inp[maxn];
 36 int ret,ans,sum;
 37 void insert(int x,int y,int v,int c)
 38 {
 39     e[++tot].go=y;e[tot].next=head[x];e[tot].v=v;e[tot].c=c;head[x]=tot;
 40 }
 41 void dp(int x)
 42 {
 43     f[x]=0;
 44     for(int i=head[x],y;i;i=e[i].next)
 45     {
 46         y=e[i].go;
 47         dp(y);
 48         f[x]+=min(e[i].v,f[y]);
 49     }
 50     if(!head[x])f[x]=inf;
 51 }
 52 void dfs(int x,int z)
 53 {
 54     s[x]=1;
 55     for(int y=son[x]=0,i=head[x];i;i=e[i].next)
 56      {
 57          fa[y=e[i].go]=x;dfs(y,z+e[i].c);
 58          b[y]=e[i].v;
 59          s[x]+=s[y];if(s[y]>s[son[x]])son[x]=y;
 60      }
 61     if(!head[x]){a[++sum].x=z;a[sum].y=x;} 
 62 }
 63 void dfs2(int x,int chain)
 64 {
 65     p[x]=++cnt;top[x]=chain;
 66     if(son[x])dfs2(son[x],chain);
 67     for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
 68      if(y!=son[x])dfs2(y,y);
 69 }
 70 void pushup(int k)
 71 {
 72     t[k].mi=min(t[k<<1].mi,t[k<<1|1].mi);
 73 }
 74 void update(int k,int z)
 75 {
 76     t[k].tag+=z;
 77     t[k].mi-=z;
 78 }
 79 void pushdown(int k)
 80 {
 81     if(!t[k].tag)return;
 82     update(k<<1,t[k].tag);
 83     update(k<<1|1,t[k].tag);
 84     t[k].tag=0;
 85 }
 86 void build(int k,int l,int r)
 87 {
 88     t[k].l=l;t[k].r=r;t[k].tag=0;
 89     if(l==r){t[k].mi=v[l];return;};
 90     int mid=(l+r)>>1;
 91     build(k<<1,l,mid);build(k<<1|1,mid+1,r);
 92     pushup(k);
 93 }
 94 void change(int k,int x,int y,int z)
 95 {
 96     int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
 97     if(l==x&&r==y){update(k,z);return;}
 98     pushdown(k);
 99     if(y<=mid)change(k<<1,x,y,z);
100     else if(x>mid)change(k<<1|1,x,y,z);
101     else change(k<<1,x,mid,z),change(k<<1|1,mid+1,y,z);
102     pushup(k);
103 }
104 int query(int k,int x,int y)
105 {
106     int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
107     if(l==x&&r==y)return t[k].mi;
108     pushdown(k);
109     if(y<=mid)return query(k<<1,x,y);
110     else if(x>mid)return query(k<<1|1,x,y);
111     else return min(query(k<<1,x,mid),query(k<<1|1,mid+1,y));
112 }
113 int getmin(int x)
114 {
115     int tt=inf;
116     while(top[x]!=root)
117      {
118          tt=min(tt,query(1,p[top[x]],p[x]));
119          x=fa[top[x]];
120      }
121     tt=min(tt,query(1,1,p[x]));
122     return tt;
123 }
124 void solvechange(int x,int y)
125 {
126     while(top[x]!=root)
127     {
128         change(1,p[top[x]],p[x],y);
129         x=fa[top[x]];
130     }
131     change(1,1,p[x],y);
132 }
133 inline bool cmp(rec a,rec b)
134 {
135     return a.x<b.x;
136 }
137 int main()
138 {
139     freopen("input.txt","r",stdin);
140     freopen("output.txt","w",stdout);
141     n=read();
142     for1(i,n-1)
143     {
144         int x=read(),y=read(),v=read(),c=read();
145         insert(x,y,v,c);
146         inp[y]++;
147     }
148     for1(i,n)if(!inp[i])root=i;
149     dp(root);
150     dfs(root,0);
151     dfs2(root,root);
152     sort(a+1,a+sum+1,cmp);
153     for1(i,n)v[p[i]]=b[i];
154     v[1]=inf;
155     build(1,1,n);
156     ans=f[1];printf("%d\n",ans);
157     ret=0;
158     for1(i,sum)
159     {
160         int tmp=min(ans,getmin(a[i].y));
161         ret+=tmp*a[i].x;
162         solvechange(a[i].y,tmp);
163         ans-=tmp;
164         if(ans==0)break;
165     }
166     printf("%d\n",ret);
167     return 0;
168 }
View Code

 

posted @ 2014-10-02 23:07  ZYF-ZYF  Views(194)  Comments(0Edit  收藏  举报