hdu3339 spfa()+dp 如果让我说:我只能说,实力决定一切

来源:互联网 发布:记忆力训练软件 编辑:程序博客网 时间:2024/04/30 12:05
题意:有N个电站,每个电站有一个能量,有多个rank,它们都在0位置,然后去破坏这个电站,当rank破坏的能量大于总能量的一半时,求出最短路程
思路:①先用spfa()求出从0到其它点的最短距离
      ②然后求出所有能量sum/2+1;
         ③利用01背包求解:从0到任意点的最短距离之和为包的容量,以每个电站的能源为价值。
      ④直接查找当包的容量>=sum时,输出最短路径即可:
    
#include<iostream>#include<cstdio>#include<string.h>#include<queue>using namespace std;queue<int>Q;const int inf=1<<30;const int maxn=10010;const int node=111;int head[maxn];int dis[maxn];int vis[node];int T,N,M,st,ed,disn;struct Edge{    int v,w,next;}e[2*maxn];int op[node],num[node];int dp[maxn];void init(){    for(int i=0; i<maxn; i++)    {        head[i]=-1;        dp[i]=0;    }    memset(vis,0,sizeof(vis));    for(int i=0;i<111;i++)        dis[i]=inf;}int MAX(int a,int b){    return a>b?a:b;}void Build_Gra(int u,int v,int w){    e[T].v=v;    e[T].w=w;    e[T].next=head[u];    head[u]=T++;}void spfa(int pox)//把点放进去。{    dis[pox]=0;    vis[pox]=1;    Q.push(pox);    while(!Q.empty())    {        int tem=Q.front();        Q.pop();        vis[tem]=0;        for(int i=head[tem]; i!=-1; i=e[i].next)        {            int gh=e[i].v;            if(dis[gh]>dis[tem]+e[i].w)            {                dis[gh]=dis[tem]+e[i].w;                if(!vis[gh])                {                    vis[gh]=1;                    Q.push(gh);                }            }        }    }}int main(){    int t;    int sum=0;    int count;    scanf("%d",&t);    while(t--)    {        T=0;        init();        count=sum=0;        scanf("%d%d",&N,&M);        for(int i=0; i<M; i++)        {            scanf("%d%d%d",&st,&ed,&disn);            Build_Gra(st,ed,disn);            Build_Gra(ed,st,disn);        }        for(int i=1; i<=N; i++)        {            scanf("%d",&num[i]);            sum+=num[i];//求总能量。        }        spfa(0);        for(int i=1; i<=N; i++)            if(dis[i]!=inf)                count+=dis[i];//最短路径总和。        sum=sum/2+1;        for(int i=0; i<maxn; i++)            dp[i]=0;        for(int i=1; i<=N; i++)            for(int j=count; j>=dis[i]; j--)//dp[]记录的是最短路径            {                dp[j]=MAX(dp[j],dp[j-dis[i]]+num[i]);            }        int r;        int flag=0;        for(r=0; r<=count; r++)        {            if(dp[r]>=sum)            {                flag=r;                break;            }        }        if(flag==0)            printf("impossible\n");        else            printf("%d\n",r);    }    return 0;}

原创粉丝点击