题意:链接
方法:线性规划
解析:
这道题我也是orz了。
刚开始脑抽,仅仅是认为所有标号为1的边都比标号为0的边小即可。
后来与140142讨论了下发现我俩都犯好sb的错误=-=
这个图也是建了一阵子。
回忆之前做过的有关一个无向联通图中,一个边在最小生成树上,必要条件是该边构成的环中,这一边一定不是最大值。
这样的话,题中既然给了在树上的边。
并且很显然树上的边只能增加,不在树上的边只能减小。
所以我们不妨设Xi代表第i条边的变化值
那么我们可以重新显然定义代价Ci。
结合之前的结论
编号为j的标号为0的一条边,与树中的i,k边形成环。
则有如下限制
Xj+Wj>=Wi?Xi
Xj+Wj>=Wk?Xk
则
Xi+Xj>=Wi?Wj
Xk+Xj>=Wk?Wj
我们可以列出所有诸如此类的限制,并且对于本题的数据,该限制不超过4000。
我们的目标函数是什么?
最小化∑mi=1Xi?Ci
这种形式是不是有点眼熟?
是的,直接用对偶原理即可求解。
然而,该题仍有一种较神的写法博主没有写过
就是这种没有基本可行解的线性规划,我们可以设一个辅助变量来求解。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 310
#define M 1010
#define INF 0x7f7f7f7f
using namespace std;
double a[M][M<<2];
int st[N];
struct line
{
int u,v,w,ff,a,b;
}l[M];
int head[N],cnt,n,m,top,tot;
struct node
{
int from,to,ff,no,a,b,next;
}edge[M<<1];
void init()
{
memset(head,-1,sizeof(head));cnt=1;
}
void edgeadd(int from,int to,int ff,int no)
{
edge[cnt].from=from,edge[cnt].to=to,edge[cnt].ff=ff,edge[cnt].no=no;
edge[cnt].next=head[from];
head[from]=cnt++;
}
void dfs(int now,int fa,int e,int edge0)
{
if(now==e)
{
while(top)
{
tot++;
int no=st[top--];
a[no][tot]=1;
a[edge0][tot]=1;
a[0][tot]=l[no].w-l[edge0].w;
}
return;
}
for(int i=head[now];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(to==fa)continue;
st[++top]=edge[i].no;
dfs(to,now,e,edge0);
st[top--]=0;
}
}
int check()
{
for(int i=1;i<=tot;i++)
if(a[0][i]>0)return i;
return 0;
}
void Simplex()
{
while(int t=check())
{
double limit=INF;
int choseline;
for(int i=1;i<=m;i++)
{
if(a[i][t]<=0)continue;
else if(a[i][0]/a[i][t]<limit)limit=a[i][0]/a[i][t],choseline=i;
}
if(limit==INF){a[0][0]=INF;break;}
double di=a[choseline][t];
for(int i=0;i<=tot;i++)
{
if(i==t)a[choseline][i]/=di;
a[choseline][i]/=di;
}
for(int i=0;i<=m;i++)
{
if(i==choseline||a[i][t]==0)continue;
if(i==0)a[i][0]+=a[i][t]*a[choseline][0];
else a[i][0]-=a[i][t]*a[choseline][0];
double l=a[i][t];
for(int j=1;j<=tot;j++)
{
if(j==t)a[i][j]=-l*a[choseline][j];
else a[i][j]-=l*a[choseline][j];
}
}
}
}
int main()
{
init();
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int u,v,w,ff,A,b,no;
scanf("%d%d%d%d%d%d",&u,&v,&w,&ff,&A,&b);
l[i].u=u,l[i].v=v,l[i].w=w,l[i].ff=ff,l[i].a=A,l[i].b=b;
if(ff)a[i][0]=b;
else a[i][0]=A;
if(ff)edgeadd(u,v,ff,i),edgeadd(v,u,ff,i);
}
for(int i=1;i<=m;i++)
{
if(l[i].ff==0)
{
top=0;
dfs(l[i].u,0,l[i].v,i);
}
}
Simplex();
printf("%.0lf\n",a[0][0]);
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-14 14:43:29