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 }