Network Wars
题目大意:
给定一个无向连通图,求一组割,要求 割的和割边数 割 的 和 割 边 数 最小。
解:
显然是一个01分数规划。推一推就做出来了。
ans∗∑xi=∑wi
a
n
s
∗
∑
x
i
=
∑
w
i
∑(wi−ans∗xi)=0
∑
(
w
i
−
a
n
s
∗
x
i
)
=
0
二分求解一下即可。
需要注意的是,ans可能是小数,需要实数域的网络流。
code(不加当前弧要TLE很优秀。zzoj):
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
struct lxy{
int to,next;
double flow;
}b[805];
struct lll{
int x,y;
double z;
}data[405];
int n,m,cnt=-1,head[105],s,t,bcnt;
double num;
int layer[105];
bool vis[105];
int ans[405];
int cir[105];
bool QAQ(double k){
if(k<0.000000000001&&-k<0.00000000001) return true;
return false;
}
void add(int op,int ed,double flow)
{
b[++cnt].next=head[op];
b[cnt].to=ed;
b[cnt].flow=flow;
head[op]=cnt;
}
bool bfs()
{
memset(cir,0,sizeof(cir));
memset(layer,0,sizeof(layer));
queue <int> d;
layer[s]=1;d.push(s);
while(!d.empty())
{
int now=d.front();
d.pop();
for(int i=head[now];i!=-1;i=b[i].next)
if(!QAQ(b[i].flow)&&layer[b[i].to]==0)
{
layer[b[i].to]=layer[now]+1;
d.push(b[i].to);
}
}
return layer[t];
}
double dfs(int u,double a)
{
if(cir[u]==0) cir[u]=head[u];
if(QAQ(a)||u==t) return a;
double f,flow=0;
for(int &i=cir[u];i!=-1;i=b[i].next)
if(!QAQ(b[i].flow)&&layer[u]+1==layer[b[i].to])
{
f=dfs(b[i].to,min(a,b[i].flow));
b[i].flow-=f;
b[i^1].flow+=f;
flow+=f;
a-=f;
if(QAQ(a)) break;
}
return flow;
}
double dinic()
{
double ans=0;
while(bfs())
ans+=dfs(s,1000000000);
return ans;
}
void findit(int u){
vis[u]=1;
for(int i=head[u];i!=-1;i=b[i].next)
if(!QAQ(b[i].flow)&&vis[b[i].to]==0)
findit(b[i].to);
}
void er(double l,double r){
cnt=-1,s=1,t=n,num=0,bcnt=0;
memset(b,0,sizeof(b));
memset(head,-1,sizeof(head));
double mid=(l+r)/2;
for(int i=1;i<=m;i++){
if(data[i].z-mid<=0) num+=data[i].z-mid,ans[++bcnt]=i;
else add(data[i].x,data[i].y,data[i].z-mid),add(data[i].y,data[i].x,data[i].z-mid);
}
double tem=dinic()+num;
if(r-l<0.00000001){
memset(vis,0,sizeof(vis));
findit(1);
for(int i=1;i<=m;i++)
if((vis[data[i].x]^vis[data[i].y])==1&&data[i].z-mid>0)
ans[++bcnt]=i;
return;
}
else if(tem<0) er(l,mid);
else er(mid,r);
}
int main()
{
int first=1;
while(scanf("%d%d",&n,&m)==2) {
if(first==0) printf("\n");
first=0;
for(int i=1;i<=m;i++)
scanf("%d%d%lf",&data[i].x,&data[i].y,&data[i].z);
er(0,10000000);
sort(ans+1,ans+1+bcnt);
printf("%d\n",bcnt);
if(bcnt!=0) cout<<ans[1];
for(int i=2;i<=bcnt;i++) printf(" %d",ans[i]);
}
}