最短路+01背包
题目数据规模小,先floyd求出两点间最短路径
在01背包的模型中,这里两点间距离就是花费,背包容量是所有物品到起点0的花费和
先求出所有状态下最大value值,然后从小到大枚举花费,value最先>sum/2的就是答案了
WA点:重边、题目要求>sum/2
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f
#define ll __int64
using namespace std;
int n,m,dp[10010],mp[110][110],w[110];
void floyd()
{
int i,j,k;
for(i=0;i<=n;i++)
for(j=0;j<=n;j++)
for(k=0;k<=n;k++)
{
if(mp[j][k]>mp[j][i]+mp[i][k])
mp[j][k]=mp[j][i]+mp[i][k];
}
}
int main()
{
int t,i,j,v,sum,a,b,c;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(i=0;i<=n;i++)
{
for(j=0;j<=n;j++)
{
if(i==j) mp[i][j]=0;
else mp[i][j]=inf;
}
}
for(i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
mp[a][b]=mp[b][a]=min(mp[a][b],c);
}
floyd();
sum=v=0;
for(i=1;i<=n;i++)
{
scanf("%d",&w[i]);
sum+=w[i];
if(mp[0][i]!=inf) v+=mp[0][i];
}
sum=sum/2;
memset(dp,0,sizeof dp);
for(i=1;i<=n;i++)
{
if(mp[0][i]!=inf)
for(j=v;j>=mp[0][i];j--)//判断条件╮(╯▽╰)╭
dp[j]=max(dp[j],dp[j-mp[0][i]]+w[i]);
}
int flag=0;
for(i=1;i<=v;i++)
{
if(dp[i]>sum)
{
flag=1;
printf("%d\n",i);
break;
}
}
if(!flag)
printf("impossible\n");
}
return 0;
}