国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

bzoj 3118: Orz the MST (單純形)

2019-11-06 06:21:55
字體:
供稿:網(wǎng)友

3118: Orz the MST

Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 236  Solved: 98[Submit][Status][Discuss]

Description

給出一個(gè)帶權(quán)的連通無向圖,對(duì)于其中的每條邊i,在原來邊權(quán)的基礎(chǔ)上,其邊權(quán)每增加1需要付出的代價(jià)為Ai,邊權(quán)每減少1需要付出的代價(jià)為Bi,現(xiàn)在指定該圖的一棵生成樹,求通過修改邊權(quán),使得該生成樹成為圖的一棵最小生成樹,需要付出的最少總代價(jià)。 

Input

第一行兩個(gè)正整數(shù)N, M,表示圖的點(diǎn)數(shù)和邊數(shù),點(diǎn)以1~N編號(hào);接下來M行,每行六個(gè)正整數(shù)Ui, Vi, Wi, FFi, Ai, Bi,表示一條邊(Ui, Vi)權(quán)為Wi,在原邊權(quán)基礎(chǔ)上增加1的邊權(quán)代價(jià)為Ai,減少1的邊權(quán)代價(jià)為Bi,F(xiàn)Fi若為1則表示該邊在指定的生成樹中,若為0表示不在。數(shù)據(jù)保證FF值為1的邊剛好組成原圖的一棵生成樹。兩點(diǎn)之間可能有多條不同的邊,但沒有連接同一點(diǎn)的邊。 

Output

 輸出一個(gè)正整數(shù),表示所需付出的最少總代價(jià)。 

Sample Input

6 81 2 3 1 4 21 4 2 0 3 42 3 5 1 2 12 4 4 1 3 53 5 2 0 1 33 6 1 0 2 44 5 7 1 3 25 6 5 1 5 4

Sample Output

21

HINT

【Hint】樣例解釋:最優(yōu)方案為:(1, 4)邊權(quán)加2,代價(jià)6;(3, 5)邊權(quán)加3,代價(jià)3;(3, 6)邊權(quán)加4,代價(jià)8;(4, 5)邊權(quán)減2,代價(jià)4;總代價(jià)21。數(shù)據(jù)范圍:1<=N<=300, 1<=M, Wi, Ai, Bi<=1000。

Source

Mato_No1提供

[Submit][Status][Discuss]

題解:?jiǎn)渭冃?/p>

一道不錯(cuò)的單純形,需要用心想一下。

首先對(duì)于樹邊只可能減少,非樹邊只可能增加。

我們把樹建好,考慮增加一條非樹邊,在什么情況下可能會(huì)替代一條樹邊,成為新的最小生成樹?當(dāng)非樹邊的兩個(gè)端點(diǎn)之間路徑上的邊有比當(dāng)前非樹邊小的時(shí)候,可以替換。

所有我們要保證路徑上的所有邊最終權(quán)值小于等于這條非樹邊。

那么我們可以得到wi-xi<=wj+xj,移項(xiàng)的xi+xj>=wi-wj

然后就得到了多個(gè)類似的式子,在滿足所有式子的基礎(chǔ)上最小化sigma (xi*c[i])

因?yàn)槲覀兊玫降氖阶邮谴笥诘扔冢孕枰玫綄?duì)偶定理來轉(zhuǎn)化求解。

#include<iostream>  #include<cstdio>  #include<algorithm>  #include<cstring>  #include<cmath>  #define N 1003  #define M 4003  #define eps 1e-8  using namespace std;  const double inf=1e20;int n,m,point[N],tot,nxt[N],v[N],num[N],c1[N],deep[N],val[N],pos[N],fa[N],cnt;  double ans,v1,b[M],a[N][M],c[M];  struct data{      int u,v,w,a,b,opt;  }e[N],e1[N];  void PRiov(int l,int e)  {      b[l]/=a[l][e];      for (int i=1;i<=m;i++)       if (i!=e) a[l][i]/=a[l][e];      a[l][e]=1/a[l][e];      for (int i=1;i<=n;i++)       if (fabs(a[i][e])>eps&&i!=l) {          b[i]-=b[l]*a[i][e];          for (int j=1;j<=m;j++)           if (j!=e) a[i][j]-=a[i][e]*a[l][j];          a[i][e]=-a[i][e]*a[l][e];       }      v1+=c[e]*b[l];      for (int i=1;i<=m;i++)       if (i!=e) c[i]-=c[e]*a[l][i];      c[e]=-c[e]*a[l][e];  }  double simple()  {      int i,l,e;      double t;      while (true){          for (i=1;i<=m;i++)            if (c[i]>eps) break;          e=i;          if (e==m+1) return v1;          t=inf;          for (int i=1;i<=n;i++)            if (a[i][e]>eps&&t>b[i]/a[i][e])             t=b[i]/a[i][e],l=i;          if (t==inf) return inf;          priov(l,e);      }  }  void add(int x,int y,int z,int k)  {      tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c1[tot]=z; num[tot]=k;      tot++; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; c1[tot]=z; num[tot]=k;      //cout<<x<<" "<<y<<" "<<z<<endl;  }  void dfs(int x,int f)  {      deep[x]=deep[f]+1;      for (int i=point[x];i;i=nxt[i]){          if (v[i]==f) continue;          val[v[i]]=c1[i]; pos[v[i]]=num[i];          fa[v[i]]=x;          dfs(v[i],x);      }  }  void solve(int x,int y,int i)  {      while (x!=y) {          if (deep[x]>deep[y]) {              if (val[x]>e[i].w) {                  ++cnt; a[i][cnt]=1; a[pos[x]][cnt]=1;                  //cout<<i<<" "<<pos[x]<<endl;                  c[cnt]=val[x]-e[i].w;              }              x=fa[x];          }          else {              if (val[y]>e[i].w) {                  ++cnt; a[i][cnt]=1; a[pos[y]][cnt]=1;                  //cout<<i<<" "<<pos[y]<<endl;                  c[cnt]=val[y]-e[i].w;              }              y=fa[y];          }      }  }  int main()  {      freopen("a.in","r",stdin);      freopen("my.out","w",stdout);    scanf("%d%d",&n,&m);      for (int i=1;i<=m;i++) {         scanf("%d%d%d%d%d%d",&e[i].u,&e[i].v,&e[i].w,&e[i].opt,&e[i].a,&e[i].b);         if (e[i].opt) add(e[i].u,e[i].v,e[i].w,i),b[i]=e[i].b;         else b[i]=e[i].a;      }      dfs(1,0);     cnt=0;      for (int i=1;i<=m;i++) {          if (e[i].opt) continue;          solve(e[i].u,e[i].v,i);      }      n=cnt; swap(n,m);      /*for (int i=1;i<=m;i++) cout<<b[i]<<" "; cout<<endl;	for (int i=1;i<=n;i++) cout<<c[i]<<" "; cout<<endl;	for (int i=1;i<=m;i++,cout<<endl)	  for (int j=1;j<=n;j++) cout<<a[i][j]<<" ";	cout<<endl; */    ans=simple();      printf("%.0lf/n",ans);  }  


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 博乐市| 台山市| 凯里市| 福建省| 建平县| 永春县| 安平县| 呼玛县| 庆元县| 塘沽区| 重庆市| 砚山县| 花垣县| 收藏| 五河县| 广东省| 广元市| 马公市| 伊金霍洛旗| 临海市| 体育| 抚顺市| 长泰县| 泰顺县| 永修县| 山东省| 贵港市| 和林格尔县| 田林县| 罗田县| 安陆市| 眉山市| 仙桃市| 泰顺县| 岢岚县| 康马县| 双辽市| 遵化市| 德惠市| 大田县| 石楼县|