菲律宾海战

这个题没有什么可写的部分分吧

比较套路的一个题

两种其实差不多的解法

1,DP最短路

回顾最短路的实现中,我们用len[i]表示从起点到i这个点的最短距离

那么加入减小边权了呢,我们可以用len[i][j]表示到第i个点,用掉k次减少边权机会的最小距离

转移是显然的,在普通最短路转移的基础上,加入从用掉j个支援到用j+1个的转移,

len[v][j+1]=min(len[v][j+1],len[u][j]+dis[u][v]/2)

最后取min(len[n][i])(i属于{[1,k]})即可

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int maxn=60;
int n,m,ki,len[maxn][maxn],e[maxn][maxn];
bool exist[maxn][maxn];
int spfa()
{
    queue<int>q,qs;
    memset(len,0x3f,sizeof(len));
    len[1][0]=0;
    exist[1][0]=1;
    q.push(1),qs.push(0);
    while(!q.empty())
    {
        int i=q.front(),k=qs.front();
        q.pop(),qs.pop();
        exist[i][k]=0;
        for(int j=1;j<=n;j++)
        {
            if(e[i][j]>1e6)
                continue;
            if(len[j][k]>len[i][k]+e[i][j])
            {
                len[j][k]=len[i][k]+e[i][j];
                if(!exist[j][k])
                    exist[j][k]=1,q.push(j),qs.push(k);
            }
            if(len[j][k+1]>len[i][k]+e[i][j]/2)
            {
                len[j][k+1]=len[i][k]+e[i][j]/2;
                if(!exist[j][k+1]&&k<ki)
                    exist[j][k+1]=1,q.push(j),qs.push(k+1);
            }
        }
    }
    int ret=1e9;
    for(int i=0;i<=ki;i++)
        ret=min(ret,len[n][i]);
    return ret;
}
int main()
{
    scanf("%d%d%d",&n,&m,&ki);
    memset(e,0x3f,sizeof(e));
    for(int x,y,d,i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&d);
        e[x][y]=e[y][x]=d;
    }
    printf("%d\n",spfa());
    return 0;
}


2,分层图最短路

本来是有n个点的,但是不好处理,我们不妨把每个点拆成k+1个,第j个表示到这个点要用j次支援

建图的时候同层正常连边,本层到上层连边时边权除2,直接跑最短路,统计答案时枚举第n个点各层最小代价即可

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int maxn=2600;
struct edge{
    int next,to,dis;
}e[210010];
int cnt,head[maxn],n,m,ki,len[maxn];
bool exist[maxn];
inline void add(int x,int y,int d)
{
    e[++cnt].next=head[x];
    e[cnt].to=y;
    e[cnt].dis=d;
    head[x]=cnt;
}
int spfa()
{
    queue<int> q;
    memset(len,0x3f,sizeof(len));
    q.push(1);
    len[1]=0;
    exist[1]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        exist[u]=0;
        for(int v,i=head[u];i;i=e[i].next)
            if(len[v=e[i].to]>len[u]+e[i].dis)
            {
                len[v]=len[u]+e[i].dis;
                if(!exist[v])
                    exist[v]=1,q.push(v);
            }
    }
    int ret=1e9;
    for(int i=1;i<=ki+1;i++)
        ret=min(ret,len[n*i]);
    return ret;
}
int main()
{
    scanf("%d%d%d",&n,&m,&ki);
    memset(e,0x3f,sizeof(e));
    for(int x,y,d,i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&d);
        for(int j=0;j<=ki;j++)
        {
            add(x+j*n,y+j*n,d),add(y+j*n,x+j*n,d);
            if(j<ki)
                add(x+j*n,y+(j+1)*n,d/2),add(y+j*n,x+(j+1)*n,d/2);
        }
    }
    printf("%d\n",spfa());
    return 0;
}
posted @ 2018-09-17 20:06  Ivanovcraft  阅读(204)  评论(0编辑  收藏  举报