计蒜客 31001 - Magical Girl Haze - [最短路][2018ICPC南京网络预赛L题]

题目链接:https://nanti.jisuanke.com/t/31001

题意:

一带权有向图,有 n 个节点编号1~n,m条有向边,现在一人从节点 1 出发,他有最多 k 次机会施展魔法使得某一条边的权变成 0,问他走到节点 n 的最小权值为多少。

题解:

将dist数组和vis数组都扩展一维:

dist[c][i]代表:已经使用了 c 次变0魔法后,走到节点 i 的最短距离;

vis[c][i]代表:已经使用了 c 次变0魔法后,走到节点 i 的最短距离,这个最短距离是否已经被准确计算完毕。

然后就是稍微改动一下原来的优先队列优化Dijkstra即可。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn=1e5+10;
const int maxm=2e5+10;
const int maxk=13;
const ll INF=0x3f3f3f3f3f3f3f3f;

int n,m,k;

struct Edge{
    int u,v;
    ll w;
    Edge(int u=0,int v=0,ll w=0){this->u=u,this->v=v,this->w=w;}
};
vector<Edge> E;
vector<int> G[maxn];
void init(int l,int r)
{
    E.clear();
    for(int i=l;i<=r;i++) G[i].clear();
}
void addedge(int u,int v,ll w)
{
    E.push_back(Edge(u,v,w));
    G[u].push_back(E.size()-1);
}

struct Qnode{
    int vertex;
    ll dist;
    int cnt;
    Qnode(int v=0,ll d=0,int c=0){this->vertex=v,this->dist=d,this->cnt=c;}
    bool operator <(const Qnode &oth)const{
        return dist>oth.dist;
    }
    //优先队列默认是降序排列,如果本节点小于另一个节点的意义是 本节点dist < 另一个节点dist,
    //则优先队列的队首放的就是最大的节点,就是dist最大的节点,显然我们要的是相反的情况,
    //所以设置本节点小于另一个节点的意义是 本节点dist > 另一个节点dist 即可。
};

ll dist[maxk][maxn];
bool vis[maxk][maxn];
void dijkstra(int s)
{
    for(int i=1;i<=n;i++)
    {
        for(int c=0;c<=k;c++)
        {
            dist[c][i]=((i==s)?0:INF);
            vis[c][i]=0;
        }
    }

    priority_queue<Qnode> Q;
    Q.push(Qnode(s,0,0));
    while(!Q.empty())
    {
        int u=Q.top().vertex, c=Q.top().cnt; Q.pop();
        if(vis[c][u]) continue;
        vis[c][u]=1;
        for(int i=0;i<G[u].size();i++)
        {
            Edge &e=E[G[u][i]]; int v=e.v;
            if(!vis[c][v] && dist[c][v]>dist[c][u]+e.w)
            {
                dist[c][v]=dist[c][u]+e.w;
                Q.push(Qnode(v,dist[c][v],c));
            }
            if(c+1<=k && !vis[c+1][v] && dist[c+1][v]>dist[c][u])
            {
                dist[c+1][v]=dist[c][u];
                Q.push(Qnode(v,dist[c+1][v],c+1));
            }
        }
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&k);
        init(1,n);
        for(int i=1;i<=m;i++)
        {
            int u,v; ll w;
            scanf("%d%d%lld",&u,&v,&w);
            addedge(u,v,w);
        }
        dijkstra(1);
        ll ans=INF;
        for(int c=0;c<=k;c++) ans=min(ans,dist[c][n]);
        printf("%lld\n",ans);
    }
}

原文地址:https://www.cnblogs.com/dilthey/p/9594990.html

时间: 2024-08-30 09:39:00

计蒜客 31001 - Magical Girl Haze - [最短路][2018ICPC南京网络预赛L题]的相关文章

计蒜客 30999 - Sum - [找规律+线性筛][2018ICPC南京网络预赛J题]

题目链接:https://nanti.jisuanke.com/t/30999 样例输入258 样例输出814 题意: squarefree数是指不含有完全平方数( 1 除外)因子的数, 现在一个数字 $n$,可以表示成两个squarefree数 $a,b$ 相乘,即 $n = ab$, 假设 $f\left( n \right)$ 代表了 $n$ 分解成不同的数对 $\left( {a,b} \right)$ 的个数, 现在给你一个 $n$,要求 $f\left( 1 \right) + f\

计蒜客 30990 - An Olympian Math Problem - [简单数学题][2018ICPC南京网络预赛A题]

题目链接:https://nanti.jisuanke.com/t/30990 Alice, a student of grade 6, is thinking about an Olympian Math problem, but she feels so despair that she cries. And her classmate, Bob, has no idea about the problem. Thus he wants you to help him. The proble

【推导】计蒜客17119 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 F. Trig Function

题意:给你n,m,让你求cos(nx)的展开式的(cos(x))^m项的系数. 更一般的式子是这样的:. 队友的代码: #include<cstdio> #include<algorithm> #include<queue> #include<set> using namespace std; long long n,k,i,ans; long long mo=998244353; long long ni(long long a,long long b)

【分块】计蒜客17120 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 G. Xor

题意:给一棵树,每个点有权值.q次询问a,b,k,问你从a点到b点,每次跳距离k,权值的异或和? 预处理每个点往其根节点的路径上隔1~sqrt(n)的距离的异或和,然后把询问拆成a->lca(a,b),lca(a,b)->b,讨论一下即可,细节比较多. 队友的代码: #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algo

【找规律】计蒜客17118 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 E. Maximum Flow

题意:一张有n个点的图,结点被编号为0~n-1,i往所有编号比它大的点j连边,权值为i xor j.给你n,问你最大流. 打个表,别忘了把相邻两项的差打出来,你会发现神奇的规律……你会发现每个答案都是由某些特定的数加起来组成的,最好把它们也打出来. #include<cstdio> using namespace std; typedef long long ll; #define MOD 1000000007ll ll n; int main(){ // freopen("e.ou

【推导】计蒜客17116 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 C. Sum

题意:S(x)被定义为x的十进制表示下的数位之和.给你x,让你找一个正整数k,使得S(kx)能被233整除.k不超过2千位. 由于x不超过1000000,不论x是多少,10000000重复233次一定是合法的. #include<cstdio> using namespace std; int T,x; int main(){ scanf("%d",&T); for(;T;--T){ scanf("%d",&x); for(int i=1

【二项式定理】【推导】计蒜客17115 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 B. Coin

题意:投一枚硬币向上的概率是q/p.问你投K枚硬币,向上的枚数为偶数枚的概率是? 要求的即为. 这个东西是个二项展开式的偶数项系数和,来,我们复习一下高中数学,设f(x)=(ax+b)^n,则其偶数项系数和为(f(1)+f(-1))/2. #include<cstdio> using namespace std; typedef long long ll; #define MOD 1000000007ll int T; ll p,q,K; ll Quick_Pow(ll a,ll p,ll m

【计算几何】【圆反演】计蒜客17314 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 G. Finding the Radius for an Inserted Circle

题意:给你三个半径相同的圆,它们切在一起,然后让你往缝里一个一个地塞圆,问你塞到第k个的半径是多少. 就把上面那两个圆的切点当成反演中心,然后会反演成这个样子,两个平行直线和一个圆. 然后就是往那个圆上面再塞圆,然后反演回去算面积就行了. #include<cstdio> #include<cmath> using namespace std; const double pi=3.14159; int n,K; double R,anss[12]; int main(){ //fr

计蒜客 31452 - Supreme Number - [简单数学][2018ICPC沈阳网络预赛K题]

题目链接:https://nanti.jisuanke.com/t/31452 A prime number (or a prime) is a natural number greater than $1$ that cannot be formed by multiplying two smaller natural numbers. Now lets define a number $N$ as the supreme number if and only if each number m