Codeforce544C Writing Code

题意:输入n个点,m条无向边(n,m<3000),接着输入s1, t1, l1, s2, t2, l2问最多可以删多少条边,使得s1到t1距离最多为l1, s2到t2距离最多为l2

题解:可以发现有三种情况

第一种是不可能情况

第二种是s1->t1, s2->t2没有重复的边,那么答案就是m-(d[s1][t1]+d[s2][t2])

第三种是有重复的边,这时候会形成一个类似H形状的图,只要枚举中间重复的边,计算答案就可以

注意这里不能用floyed来算最短路,O(n^3),因为边较少且为正,可以n次dijstra, 复杂度O(VE + V*V*logV)

或者n次bfs也可以

#include <bits/stdc++.h>
#define maxn 3010
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
struct edge{
    int from,to,dist;
};
struct node{
    int d,u;
    bool operator<(const node& a) const{
        return d>a.d;
    }
};
int d[maxn][maxn];
struct dij{
    int n,m;
    vector<int >G[maxn];
    vector<edge>edges;
    bool done[maxn];
    int p[maxn];
    void init(int x){
        n = x;
        for(int i=1;i<=n;i++) G[i].clear();
        edges.clear();
    }
    void add(int a,int b,int w){
        edges.push_back((edge){a,b,w});
        m = edges.size();
        G[a].push_back(m-1);
    }
    void dijstra(int st){//计算最短路
        for(int i=1;i<=n;i++) d[st][i] = INF;
        memset(done, 0, sizeof(done));
        d[st][st] = 0;
        priority_queue<node>q;
        q.push((node){0, st});
        while(!q.empty()){
            node fi = q.top();q.pop();
            int u = fi.u;
            if(done[u]) continue;
            done[u] = 1;
            for(int i=0;i<G[u].size();i++){
                edge& e = edges[G[u][i]];
                if(e.dist+d[st][u]<d[st][e.to]){
                    d[st][e.to] = d[st][u]+e.dist;
                    p[e.to] = G[u][i];
                    q.push((node){d[st][e.to], e.to});
                }
            }
        }
    }
}dj;
int main(){
    int n, m, a, b, s1, t1, l1, s2, t2, l2;
    scanf("%d%d", &n, &m);
    dj.init(n);
    for(int i=0;i<m;i++){
        scanf("%d%d", &a, &b);
        dj.add(a, b, 1);
        dj.add(b, a, 1);
    }
    scanf("%d%d%d", &s1, &t1, &l1);
    scanf("%d%d%d", &s2, &t2, &l2);
    for(int i=1;i<=n;i++)
        dj.dijstra(i);
    if(d[s1][t1] > l1||d[s2][t2] > l2) printf("-1\n");
    else{
        int ans = d[s1][t1]+d[s2][t2];
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(d[s1][i]+d[i][j]+d[j][t1]<=l1&&d[s2][i]+d[i][j]+d[j][t2]<=l2)
                    ans = min(ans, d[i][j]+d[s1][i]+d[j][t1]+d[s2][i]+d[j][t2]);
                if(d[s1][i]+d[i][j]+d[j][t1]<=l1&&d[s2][j]+d[j][i]+d[i][t2]<=l2)
                    ans = min(ans, d[i][j]+d[s1][i]+d[j][t1]+d[s2][j]+d[i][t2]);
            }
        }
        printf("%d\n", m-ans);
    }
    return 0;
}

 

posted on 2018-02-08 10:15  2855669158  阅读(223)  评论(0编辑  收藏  举报

导航