上下界费用流 第一次自己建图 各种乱搞 跟神犇的建图好像不一样... 自己还是太弱
然后就莫名其妙的A了
总的来说,就是在没限制的原图上加超级源汇连附加边
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #define V G[p].v #define oo (1<<30) using namespace std; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x) { char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } struct edge{ int u,v,w,f; int next; }; edge G[100005]; int head[515],inum=1; inline void add(int u,int v,int f,int w,int p){ G[p].u=u; G[p].v=v; G[p].f=f; G[p].w=w; G[p].next=head[u]; head[u]=p; } inline void link(int u,int v,int f,int w){ add(u,v,f,w,inum+=2),add(v,u,0,-w,inum-1); } int s,t,S,T,Mincost; const int NQ=10000; int Q[NQ],l,r; int dis[515],ins[515],pre[515]; inline bool SPFA() { int u; for (int i=1;i<=T;i++) dis[i]=1<<30,pre[i]=0,ins[i]=0; memset(Q,0,sizeof(Q)); l=r=-1; Q[(++r)%NQ]=S; dis[S]=0; ins[S]=1; while (l!=r) { u=Q[(++l)%NQ]; ins[u]=0; for (int p=head[u];p;p=G[p].next) if (G[p].f && dis[V]>dis[u]+G[p].w) { dis[V]=dis[u]+G[p].w; pre[V]=p; if (!ins[V]) Q[(++r)%NQ]=V,ins[V]=1; } } if (dis[T]==1<<30) return false; int minimum=1<<30; for (int p=pre[T];p;p=pre[G[p].u]) minimum=min(minimum,G[p].f); for (int p=pre[T];p;p=pre[G[p].u]) { G[p].f-=minimum; G[p^1].f+=minimum; Mincost+=G[p].w*minimum; } return true; } int n,m,K; int dist[305][305]; int main() { int x,y,z; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(m); read(K); S=2*n+3; T=2*n+4; s=2*n+1; t=2*n+2; link(t,s,K,0); for (int i=1;i<=n;i++) { link(i*2-1,i<<1,oo,0); link(i<<1,t,oo,0); link(S,i<<1,1,0); link(i*2-1,T,1,0); } for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) dist[i][j]=oo/2; for (int i=1;i<=m;i++) { read(x); read(y); read(z); dist[x][y]=dist[y][x]=min(dist[x][y],z); } for(int k=0;k<=n;k++) for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) if((k<=i||k<=j)&&dist[i][j]>dist[i][k]+dist[k][j]) dist[i][j]=dist[i][k]+dist[k][j]; for(int i=0;i<=n;i++) for(int j=i+1;j<=n;j++) if(dist[i][j]!=oo/2) link(i==0?s:(i<<1),j*2-1,oo,dist[i][j]); while (SPFA()); printf("%d\n",Mincost); return 0; }