zoukankan      html  css  js  c++  java
  • [BZOJ2324][ZJOI2011]营救皮卡丘

    题面戳我

    Description

    皮卡丘被火箭队用邪恶的计谋抢走了!这三个坏家伙还给小智留下了赤果果的挑衅!为了皮卡丘,也为了正义,小智和他的朋友们义不容辞的踏上了营救皮卡丘的道路。
    火箭队一共有N个据点,据点之间存在M条双向道路。据点分别从1到N标号。小智一行K人从真新镇出发,营救被困在N号据点的皮卡丘。为了方便起见,我们将真新镇视为0号据点,一开始K个人都在0号点。
    由于火箭队的重重布防,要想摧毁K号据点,必须按照顺序先摧毁1到K-1号据点,并且,如果K-1号据点没有被摧毁,由于防御的连锁性,小智一行任何一个人进入据点K,都会被发现,并产生严重后果。因此,在K-1号据点被摧毁之前,任何人是不能够经过K号据点的。
    为了简化问题,我们忽略战斗环节,小智一行任何一个人经过K号据点即认为K号据点被摧毁。被摧毁的据点依然是可以被经过的。
    K个人是可以分头行动的,只要有任何一个人在K-1号据点被摧毁之后,经过K号据点,K号据点就被摧毁了。显然的,只要N号据点被摧毁,皮卡丘就得救了。
    野外的道路是不安全的,因此小智一行希望在摧毁N号据点救出皮卡丘的同时,使得K个人所经过的道路的长度总和最少。
    请你帮助小智设计一个最佳的营救方案吧!

    Input

    第一行包含三个正整数N,M,K。表示一共有N+1个据点,分别从0到N编号,以及M条无向边。一开始小智一行共K个人均位于0号点。
    接下来M行,每行三个非负整数,第i行的整数为Ai,Bi,Li。表示存在一条从Ai号据点到Bi号据点的长度为Li的道路。

    Output

    仅包含一个整数S,为营救皮卡丘所需要经过的最小的道路总和。

    Sample Input

    3 4 2
    0 1 1
    1 2 1
    2 3 100
    0 3 1

    Sample Output

    3

    【样例说明】

    小智和小霞一起前去营救皮卡丘。在最优方案中,小智先从真新镇前往1号点,接着前往2号据点。当小智成功摧毁2号据点之后,小霞从真新镇出发直接前往3号据点,救出皮卡丘。

    HINT

    对于100%的数据满足N ≤ 150, M ≤ 20 000, 1 ≤ K ≤ 10, Li ≤ 10 000, 保证小智一行一定能够救出皮卡丘。至于为什么K ≤ 10,你可以认为最终在小智的号召下,小智,小霞,小刚,小建,小遥,小胜,小光,艾莉丝,天桐,还有去日本旅游的黑猫警长,一同前去大战火箭队。

    sol

    K路径覆盖问题,cls以前讲过的题目,还是蛮有代表性的。
    由于(nle 150)所以我们考虑先(Floyed)求出任意两点之间的最短路。这里要注意一下,在松弛的时候一定要保证(kle max(i,j)),因为不能走后面的点啦。
    求出来以后就好办了,以下是具体建图:
    1、(S)向0号点连容量为(K),费用为0
    2、(1-n)每个点拆成两个点,(S)(i)连容量为1费用为0,(i')(T)连容量为1费用为0
    3、所有的有序对((i,j))其中(i<j)(包括0),(i)(j')连容量为1费用为(i)(j)最短路。

    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int inf = 1e9;
    const int N = 500;
    struct edge{int to,next,w,cost;}a[N*N];
    int n,m,K,len[N][N],S,T,head[N],cnt=1,dis[N],vis[N],pe[N],ans;
    queue<int>Q;
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    void link(int u,int v,int w,int cost)
    {
    	a[++cnt]=(edge){v,head[u],w,cost};
    	head[u]=cnt;
    	a[++cnt]=(edge){u,head[v],0,-cost};
    	head[v]=cnt;
    }
    bool spfa()
    {
    	for (int i=0;i<=T;i++) dis[i]=inf;
    	dis[S]=0;Q.push(S);
    	while (!Q.empty())
    	{
    		int u=Q.front();Q.pop();
    		for (int e=head[u];e;e=a[e].next)
    		{
    			int v=a[e].to;
    			if (a[e].w&&dis[v]>dis[u]+a[e].cost)
    			{
    				dis[v]=dis[u]+a[e].cost;pe[v]=e;
    				if (!vis[v]) vis[v]=1,Q.push(v);
    			}
    		}
    		vis[u]=0;
    	}
    	if (dis[T]==inf) return false;
    	int sum=inf;
    	for (int i=T;i!=S;i=a[pe[i]^1].to)
    		sum=min(sum,a[pe[i]].w);
    	ans+=sum*dis[T];
    	for (int i=T;i!=S;i=a[pe[i]^1].to)
    		a[pe[i]].w-=sum,a[pe[i]^1].w+=sum;
    	return true;
    }
    int main()
    {
    	n=gi();m=gi();K=gi();
    	S=2*n+1;T=S+1;
    	for (int i=0;i<=n;i++)
    		for (int j=0;j<=n;j++)
    			len[i][j]=(i==j)?0:inf;
    	for (int i=1;i<=m;i++)
    	{
    		int u=gi(),v=gi(),l=gi();
    		len[u][v]=len[v][u]=min(len[u][v],l);
    	}
    	for (int k=0;k<=n;k++)
    		for (int i=0;i<=n;i++)
    			for (int j=0;j<=n;j++)
    				if (k<=max(i,j))
    					len[i][j]=min(len[i][j],len[i][k]+len[k][j]);
    	link(S,0,K,0);
    	for (int i=1;i<=n;i++)
    		link(S,i,1,0),link(i+n,T,1,0);
    	for (int i=0;i<=n;i++)
    		for (int j=i+1;j<=n;j++)
    			if (len[i][j]!=inf)
    				link(i,j+n,1,len[i][j]);
    	while (spfa()) ;
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Eclipse / android studio 添加第三方jar包 步骤
    Android checkbox 自定义点击效果
    Android 程序打包和安装过程
    Android 基础
    (转)Genymotion安装virtual device的“unable to create virtual device, Server returned Http status code 0”的解决方法
    (转)eclipse 导入Android 项目 步骤
    微信开放平台注册 步骤
    Android Studio 初级安装
    数组
    作用域问题代码
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8214388.html
Copyright © 2011-2022 走看看