挖地雷

Problem Description

在一个地图上有n个地窖(n<=200),每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径,并规定路径都是单向的,也不存在可以从一个地窖出发经过若干地窖后又回到原来地窖的路径。某人可以从任一处开始挖地雷,然后沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使他能挖到最多的地雷。(用动态规划求解)

Input

输入有多组数据,每组数据的第一行为一个整数n,表示地窖的个数,第二行为n个地窖中的地雷数。下面多行数据以0,0结束,每行为两个数x和y,表示从x可以到y。

Output

对于每组数据输出两行,第一行为挖地雷的顺序,第二行为最多挖出的地雷数

Sample Input

1
6
5 10 20 5 4 5
1 2
1 4
2 4
3 4
4 5
4 6
5 6
0 0

Sample Output

3-4-5-6
34
/*
     解题报告:根据路径进行DP。(注意:要把路径先排序)
*/
 
 
// 标程:
 
 
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;


int a[210],b[210];
struct ss
{
	int x,y;
}dp[50000];
ss dp1[210];


bool cmp(ss c1,ss c2)
{
   if(c1.x!=c2.x) return c1.x<c2.x;
   else if(c1.y!=c2.y) return c1.y<c2.y;
}


int main()
{
	//freopen("b.txt","r",stdin);


	int n,m,i,x,y,t;
	scanf("%d",&t);
    while(t--)
	{
		memset(b,0,sizeof(b));  
		memset(dp1,0,sizeof(dp1));
		scanf("%d",&n);
		int max1=0,flag=0;
		for(i=1;i<=n;i++) 
					scanf("%d",&a[i]);  
			dp1[i].x=a[i];  
			if(a[i]>max1) { max1=a[i]; flag=i;}
		}
        
		int max=0,ans=0,k=0,j=0;
		while(scanf("%d%d",&x,&y))
		{
			 if(!x && !y) break;
             dp[j].x=x, dp[j].y=y;
			 j++;
        }
		sort(dp,dp+j,cmp);
		
        for(i=0;i<j;i++)
		{
			if(dp1[dp[i].y].x<dp1[dp[i].x].x+a[dp[i].y]) 
            {
				dp1[dp[i].y].x=dp1[dp[i].x].x+a[dp[i].y];
			    dp1[dp[i].y].y=dp[i].x;
			}
			if(dp1[dp[i].y].x>max) { max=dp1[dp[i].y].x, ans=dp[i].y; }
		}
		b[0]=ans;
		k=1;
		while(1)
		{
			ans=dp1[ans].y;
			if(ans==0) break;
			b[k++]=ans;
		}
		if(k>1)
		{
			for(i=k-1;i>0;i--)
		        printf("%d-",b[i]);
	        printf("%d\n",b[0]);


			printf("%d\n",max);
		}
		if(k==1) printf("%d\n%d\n",flag,max1);


        
		return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值