codeforces #378F(733.F) Drivers Dissatisfaction

来源:互联网 发布:informix导出数据库 编辑:程序博客网 时间:2024/06/05 11:04

F. Drivers Dissatisfaction
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

In one kingdom there are n cities and m two-way roads. Each road connects a pair of cities, and for each road we know the level of drivers dissatisfaction — the value wi.

For each road we know the value ci — how many lamziks we should spend to reduce the level of dissatisfaction with this road by one. Thus, to reduce the dissatisfaction with the i-th road by k, we should spend k·ci lamziks. And it is allowed for the dissatisfaction to become zero or even negative.

In accordance with the king's order, we need to choose n - 1 roads and make them the main roads. An important condition must hold: it should be possible to travel from any city to any other by the main roads.

The road ministry has a budget of S lamziks for the reform. The ministry is going to spend this budget for repair of some roads (to reduce the dissatisfaction with them), and then to choose the n - 1 main roads.

Help to spend the budget in such a way and then to choose the main roads so that the total dissatisfaction with the main roads will be as small as possible. The dissatisfaction with some roads can become negative. It is not necessary to spend whole budget S.

It is guaranteed that it is possible to travel from any city to any other using existing roads. Each road in the kingdom is a two-way road.

Input

The first line contains two integers n and m (2 ≤ n ≤ 2·105n - 1 ≤ m ≤ 2·105) — the number of cities and the number of roads in the kingdom, respectively.

The second line contains m integers w1, w2, ..., wm (1 ≤ wi ≤ 109), where wi is the drivers dissatisfaction with the i-th road.

The third line contains m integers c1, c2, ..., cm (1 ≤ ci ≤ 109), where ci is the cost (in lamziks) of reducing the dissatisfaction with the i-th road by one.

The next m lines contain the description of the roads. The i-th of this lines contain a pair of integers ai and bi (1 ≤ ai, bi ≤ nai ≠ bi) which mean that the i-th road connects cities ai and bi. All roads are two-way oriented so it is possible to move by the i-th road from aito bi, and vice versa. It is allowed that a pair of cities is connected by more than one road.

The last line contains one integer S (0 ≤ S ≤ 109) — the number of lamziks which we can spend for reforms.

Output

In the first line print K — the minimum possible total dissatisfaction with main roads.

In each of the next n - 1 lines print two integers x, vx, which mean that the road x is among main roads and the road x, after the reform, has the level of dissatisfaction vx.

Consider that roads are numbered from 1 to m in the order as they are given in the input data. The edges can be printed in arbitrary order. If there are several answers, print any of them.

Examples
input
6 91 3 1 1 3 1 2 2 24 1 4 2 2 5 3 1 61 21 32 32 42 53 53 64 55 67
output
01 13 16 17 28 -5
input
3 39 5 17 7 22 13 13 22
output
53 02 5


题目大意:n个点m条边的图,每条边有边权wi和边权减1的费用ci

你有S的总费用,让你减少一些边的边权,使得生成的最小生成树的权值总和最小



首先可以确定,我们肯定就只会减少一条边的权重,因为如果减少两条边的权重,如果他们费用相等,那显然只需要减少一条边就好了;如果他们费用不等,那么肯定只减少权重小的那条边更优

那么我们先建立最小生成树,然后枚举要减的边

如果边在树上则直接在sum中减去

如果边不在树上,假设两边是s,t,那么在树上找到s,t中间路上权值最大的边删去,加上这条边即可。这里可以用倍增LCA来维护

在枚举的时候顺便记录方案则可输出最终方案

#include<map>#include<queue>#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<algorithm>using namespace std;struct line{     int s,t; long long x,c; int p;     int next;}exa[200001],a[400001];int head[200001];int edge;inline void add(int s,int t,long long x,long long c){     a[edge].next=head[s];     head[s]=edge;     a[edge].s=s;     a[edge].t=t;     a[edge].x=x;     a[edge].c=c;}inline bool cmp1(line x,line y){return x.x<y.x;}inline bool cmp2(line x,line y){return x.p<y.p;}bool v[200001];int deep[200001];int ans[200001][22];long long anc[200001][22];int anx[200001][22];inline void bfs(int r){     int i,j;     deep[r]=1;     for(i=0;i<=21;i++)          ans[r][i]=r;     queue <int>Q;     while(!Q.empty())          Q.pop();     Q.push(r);     v[r]=true;     while(!Q.empty())     {          int d=Q.front();          Q.pop();          for(i=head[d];i!=0;i=a[i].next)          {               int t=a[i].t;               if(!v[t])               {                    v[t]=true;                    Q.push(t);                    deep[t]=deep[d]+1;                    ans[t][0]=d;                    anc[t][0]=a[i].x;                    anx[t][0]=a[i].p;                    int dt;long long dc;                    for(j=1;j<=21;j++)                    {                     dt=ans[t][j-1];                     dc=anc[t][j-1];                         ans[t][j]=ans[dt][j-1];                         if(anc[dt][j-1]>dc)                         {                         dc=max(dc,anc[dt][j-1]);                         anc[t][j]=dc;                         anx[t][j]=anx[dt][j-1];                         }                         else                         {                         anc[t][j]=dc;                         anx[t][j]=anx[t][j-1];                         }                    }               }          }     }}long long ansx;struct xx{long long x;int p;};xx ax;inline int swim(int x,int y){ int ansc=0;     while(deep[x]!=deep[y])     {          int i=0;          while(deep[ans[y][i]]>deep[x])               i++;          if(i!=0)               i--;          if(anc[y][i]>ansx)          {               ansx=max(anc[y][i],ansx);               ansc=anx[y][i];          }          y=ans[y][i];     }     ax.x=ansx;     ax.p=ansc;     return y;}inline xx lca(int x,int y){ ax.p=0; ax.x=0; ansx=0; int ansc=0;     if(deep[x]>deep[y])     {          int t=x;          x=y;          y=t;     }     y=swim(x,y);     while(x!=y)     {          int i=0;          while(ans[x][i]!=ans[y][i])               i++;          if(i!=0)               i--;         // if(anc[x][i]!=xx)          if(anc[x][i]>ansx)          {               ansx=max(anc[x][i],ansx);               ansc=anx[x][i];          }          //if(anc[y][i]!=xx)          if(anc[y][i]>ansx)          {               ansx=max(anc[y][i],ansx);               ansc=anx[y][i];          }          x=ans[x][i];          y=ans[y][i];     }     if(ansx>ax.x)     {          ax.x=ansx;          ax.p=ansc;     }     return ax;}int fa[200001];inline int find(int x){     if(fa[x]!=x)          fa[x]=find(fa[x]);     return fa[x];}long long w[200001],c[200001];int aa[200001];bool vv[200001];int main(){int n,m;scanf("%d%d",&n,&m);int i;for(i=1;i<=m;i++)scanf("%I64d",&w[i]);for(i=1;i<=m;i++)scanf("%I64d",&c[i]);for(i=1;i<=m;i++){scanf("%d%d",&exa[i].s,&exa[i].t);exa[i].x=w[i];exa[i].c=c[i];exa[i].p=i;}sort(exa+1,exa+1+m,cmp1);int sx=0;for(i=1;i<=n;i++)fa[i]=i;int p=0;long long ans=0,sum=0;for(i=1;i<=m;i++){int s=exa[i].s,t=exa[i].t;int fx=find(s),fy=find(t);if(fx!=fy){fa[fx]=fy;sx++;aa[sx]=exa[i].p;vv[exa[i].p]=true;sum+=exa[i].x;if(sx==n-1)break;}}sort(exa+1,exa+1+m,cmp2);ans=sum;for(i=1;i<=m;i++){if(!vv[i])continue;int s=exa[i].s,t=exa[i].t;long long w=exa[i].x,c=exa[i].c;edge++;a[edge].p=exa[i].p;add(s,t,w,c);edge++;a[edge].p=exa[i].p;add(t,s,w,c);}bfs(1);long long ss;scanf("%I64d",&ss);long long mini=0,minii=0;int flag=0;for(i=1;i<=m;i++){int s=exa[i].s,t=exa[i].t;if(vv[i]){if(sum-ss/exa[i].c<ans){ans=sum-ss/exa[i].c;mini=i;flag=1;}}else{xx ax=lca(s,t);if(sum-ax.x+exa[i].x-ss/exa[i].c<ans){flag=2;mini=i;minii=ax.p;ans=sum-ax.x+exa[i].x-ss/exa[i].c;}}}printf("%I64d\n",ans);if(flag==1){for(i=1;i<=m;i++){if(vv[i]){if(mini!=i)printf("%d %I64d\n",i,exa[i].x);elseprintf("%d %I64d\n",i,exa[i].x-ss/exa[i].c);}}}else{for(i=1;i<=m;i++){if(vv[i]&&i!=minii){printf("%d %I64d\n",i,exa[i].x);}else if(i==mini)printf("%d %I64d\n",i,exa[i].x-ss/exa[i].c);}}return 0;}