思考如何满足要摧毁点N,必须摧毁前N-1个点。
我们设dis[i][j]为从i到j且不经过大于max(i,j)的点的最短路。
原题转化成了求K条路径覆盖,使得这些路径的权值和最小。
考虑网络流里面的二分图模型最小路径覆盖里面的拆点。
每个点要拆成i和i’,分别表示进入这个点和出去这个点。
源点向0号点连一条容量为K,费用为0;对于每一个点i,向所有的点j(j>i这个条件是必要的)的j’连接一条容量为1,费用为dis[i][j]的边;源点向每个i连一条容量1,费用0的边;
每个i’向汇点连一条容量1,费用0的边。
跑最小费用最大流即可。
这一题我floyd时候有一个大写的K,打成小写,调了好久。。。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define X first
#define Y second
#define DB double
#define lc now<<1
#define rc now<<1|1
#define MP make_pair
#define LL long long
#define pb push_back
#define sqr(_) ((_)*(_))
#define INF 0x3f3f3f3f
#define pii pair
#define pdd pair
#define ull unsigned LL
#define DEBUG(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
template<typename T>void Read(T& x)
{
x=0;int flag=0,sgn=1;char c;
while(c=getchar())
{
if(c=='-')sgn=-1;
else if(c>='0'&&c<='9')x*=10,x+=c-'0',flag=1;
else if(flag)break;
}
x*=sgn;
}
const int MAXM=40009,MAXN=320;
int dis[160][160],first[MAXN],next[MAXM],to[MAXM],w[MAXM],n,m,k,e=0;
void add(int a,int b,int c)
{
next[e]=first[a];first[a]=e;to[e]=b;w[e]=c;++e;
next[e]=first[b];first[b]=e;to[e]=a;w[e]=c;++e;
}
struct Edge{
int u,v,cap,flow,cost;
Edge(int u=0,int v=0,int cap=0,int flow=0,int cost=0):
u(u),v(v),cap(cap),flow(flow),cost(cost){}
};
struct Mincost{
vector<int> G[MAXN];
vector edges;
int p[MAXN],d[MAXN],S,T,inq[MAXN],a[MAXN];
void add(int u,int v,int cap,int cost)
{
edges.pb(Edge(u,v,cap,0,cost));
edges.pb(Edge(v,u,0,0,-cost));
int K=edges.size();
G[u].pb(K-2);
G[v].pb(K-1);
}
bool SPFA(int& flow,int& cost)
{
memset(p,0,sizeof(p));
memset(inq,0,sizeof(inq));
memset(a,INF,sizeof(a));
memset(d,INF,sizeof(d));
queue<int> q;
q.push(S);
inq[S]=1;
d[S]=0;
while(!q.empty())
{
int u=q.front();q.pop();
inq[u]=0;
for(int i=0;iif(e.cap>e.flow&&d[e.v]>d[u]+e.cost)
{
d[e.v]=d[u]+e.cost;
p[e.v]=G[u][i];
a[e.v]=min(a[e.v],e.cap-e.flow);
if(!inq[e.v])
q.push(e.v),
inq[e.v]=1;
}
}
}
if(a[T]==INF)return 0;
flow+=a[T];
cost+=a[T]*d[T];
int U=T;
while(U!=S)
{
edges[p[U]].flow+=a[T];
edges[p[U]^1].flow-=a[T];
U=edges[p[U]].u;
}
return 1;
}
int mincost()
{
int flow=0,cost=0;
while(SPFA(flow,cost));
return cost;
}
}Graph;
int main()
{
#ifndef ONLINE_JUDGE
freopen("w.in","r",stdin);
freopen("w.out","w",stdout);
#endif
Read(n);Read(m);Read(k);
memset(dis,INF,sizeof(dis));
for(int i=1;i<=m;i++)
{
int a,b,l;
Read(a);Read(b);Read(l);
add(a,b,l);
dis[a][b]=min(dis[a][b],l);
dis[b][a]=min(dis[b][a],l);
}
for(int i=0;i<=n;i++)
dis[i][i]=0;
for(int K=0;K<=n;K++)
{
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
{
if(K>j&&K>i)continue;
dis[i][j]=min(dis[i][K]+dis[K][j],dis[i][j]);
}
}
for(int i=0;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(dis[i][j]!=INF&&i!=j)
Graph.add(i,j+n,1,dis[i][j]);
Graph.S=2*n+1,Graph.T=2*n+2;
Graph.add(Graph.S,0,k,0);
for(int i=1;i<=n;i++)
Graph.add(Graph.S,i,1,0);
for(int i=1;i<=n;i++)
Graph.add(i+n,Graph.T,1,0);
cout<