Jzzhu and Cities

题目链接
题意:
n个点,m条带权边的无向图,另外还有k条特殊边,每条边连接1和i。问最多可以删除这k条边中的多少条,使得每个点到1的最短距离不变。
思路:
显然先跑一遍最短路,分别记录首都到各个城市的最短路径的条数,随后遍历k条特殊边,考虑这条边连向的城市,如果首都到该城市的最短路小于该火车线路的距离,显然该线路可以删去,大于的情况不可能存在,最后考虑等于的情况,如果首都到该城市的最短路径数大于1,说明可以删去不影响,同时首都到该城市的最短路径数减一。具体实现见代码。

点击查看代码
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long 
const ll N = 1e6+5;
ll n,m,k;
ll M=1000000;
//存图
struct edge{
    ll next,vi,wi;
    edge(){}
    edge(ll _next,ll _vi,ll _wi){
        next=_next,vi=_vi,wi=_wi;
    }
}e[N]; 
ll head[N/10+10],index1;
void insert(ll a,ll b,ll c){
    e[index1]=edge(head[a],b,c);
    head[a]=index1++;
}
ll arr[N];
ll brr[N];
ll js[N];
ll dis[N];
bool vis[N];
multiset<pair<ll,ll>>s;
//跑最短路径和路径最短路径数
void hanshu(ll u){
    for(ll i=1;i<=n;++i){
        dis[i]=0x7fffffffffffffff;
    }
    dis[u]=0;
    s.insert({0,u});
    js[u]=1;
    while(!s.empty()){
        ll dingdian=s.begin()->second;
        s.erase(s.begin());
        if(vis[dingdian]) continue;
        vis[dingdian]=1;
        for(ll j=head[dingdian];~j;j=e[j].next){
            ll v=e[j].vi;
            ll w=e[j].wi;
            if(dis[v]>dis[dingdian]+w){
                dis[v]=dis[dingdian]+w;
                js[v]=js[dingdian]; 
                s.insert({dis[v],v});
            }else if(dis[v]==dis[dingdian]+w){
                js[v]+=js[dingdian];
                js[v]=min(js[v],M); //最短路条数会爆long long,给它限定一个不爆long long且不影响答案的数字即可
            }
        }
    }
}
void solve(){
    //初始化、读取及插边操作
    memset(head,-1,sizeof(head));
    cin>>n>>m>>k;
    for(ll i=1;i<=m;++i){
        ll a,b,c;
        cin>>a>>b>>c;
        insert(a,b,c);
        insert(b,a,c);
    }
    for(ll i=1;i<=k;++i){
        ll a=1;
        cin>>arr[i]>>brr[i];
        insert(a,arr[i],brr[i]);
        insert(arr[i],a,brr[i]);
    }
    hanshu(1);
    ll ans=0;
    //开始遍历k条特殊路径并判断是否删边
    for(ll i=1;i<=k;++i){
        ll w=brr[i];
        ll v=arr[i];
        if(dis[v]<w){
            ans++; 
        }else if(dis[v]==w){
            if(js[v]>1){
                ans++;
                js[v]--;
            }
        }
    }
    cout<<ans<<endl; //输出答案
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    ll _=1;
    // cin>>_;
    while(_--)
    solve();
    return 0;
}
posted @ 2025-01-28 13:51  sjgigj  阅读(24)  评论(0)    收藏  举报