您的位置:首页 > 其它

sgu206 分类: sgu 2015-06-10 17:00 29人阅读 评论(0) 收藏

2015-06-10 17:00 417 查看
首先很显然,生成树上的边权应减小,非生成树上的边权应增大。

令 xi=ci−di , yj=dj−cj (xi>=0,yj>=0)

若树边 i 在非树边 j 和生成树形成的环上,

有 di<=dj⟹ci−xi<=yj+cj⟹xi+yj>=ci−cj

建立二分图,其中 wi,j=ci−cj,KM 算法求最大权匹配,满足

Ai+Bj>=wi,j,即可满足该不等式。

与 差分约束系统 有着异曲同工之妙 ^_^。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>

const int MAXN = 70, MAXM = 405, INF = 0x3f3f3f3f;

int n, m;
int a[MAXM], b[MAXM], c[MAXM];
int g[MAXN][MAXN];

int nx, ny, w[MAXM][MAXM];
int link[MAXM], slack[MAXM];
int lx[MAXM], ly[MAXM];
bool visx[MAXM], visy[MAXM];

bool DFS(int fr,int a,int to,int id)
{
if(a == to) return true;

for(int i = 1; i <= n; i++)
{
if(i == fr || !g[a][i]) continue;

if(DFS(a, i, to, id))
{
int &newrc = w[g[a][i]][id];
newrc = std::max(newrc, c[g[a][i]] - c[id]);
return true;
}
}
return false;
}
void PreWork()
{
scanf("%d%d",&n,&m);

for(int i = 1; i <= m; i++)
{
scanf("%d%d%d",&a[i],&b[i],&c[i]);
if(i < n) g[a[i]][b[i]] = g[b[i]][a[i]] = i;
}
for(int i = n; i <= m; i++)
DFS(0,a[i],b[i],i);

nx = m, ny = m;
}
bool find(int x)
{
visx[x] = true;

for(int y = 1; y <= ny; y++)
if(!visy[y])
{
int cal = lx[x] + ly[y] - w[x][y];

if(cal == 0)
{
visy[y] = true;
if(!link[y] || find(link[y]))
{
link[y] = x;
return true;
}
}
slack[y] = std::min(cal, slack[y]);
}
return false;
}

void Solve()
{
memset(lx,0,sizeof(lx));
memset(ly,0,sizeof(ly));

for(int i = 1; i <= nx; i++)
for(int j = 1; j <= ny; j++)
lx[i] = std::max(lx[i], w[i][j]);

for(int i = 1; i <= nx; i++)
{
memset(slack,INF,sizeof(slack));

while(true)
{
memset(visx,false,sizeof(visx));
memset(visy,false,sizeof(visy));

if(find(i)) break;

int d = INF;

for(int j = 1; j <= ny; j++)
if(!visy[j]) d = std::min(d, slack[j]);

for(int j = 1; j <= nx; j++)
if(visx[j])lx[j] -= d;
for(int j = 1; j <= ny; j++)
if(visy[j])ly[j] += d;
else  slack[j] -= d;
}
}

}

void Output()
{
for(int i = 1; i < n; i++)
printf("%d\n",c[i]-lx[i]);
for(int i = n; i <= m; i++)
printf("%d\n",c[i]+ly[i]);
}

int main()
{
#ifndef ONLINE_JUDGE
freopen("sgu206.in","r",stdin);
freopen("sgu206.out","w",stdout);
#endif

PreWork();
Solve();
Output();

#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: