AtCoder Beginner Contest 243

比赛链接

AtCoder Beginner Contest 243

E - Edge Deletion

Problem Statement

You are given a simple connected undirected graph with \(N\) vertices and \(M\) edges.
Edge \(i\) connects Vertex \(A_{i}\) and Vertex \(B_{i}\), and has a length of \(C_{i}\).
Let us delete some number of edges while satisfying the conditions below. Find the maximum number of edges that can be deleted.

  • The graph is still connected after the deletion.
  • For every pair of vertices \((s, t)\), the distance between \(s\) and \(t\) remains the same before and after the deletion.

Notes

A simple connected undirected graph is a graph that is simple and connected and has undirected edges.
A graph is simple when it has no self-loops and no multi-edges.
A graph is connected when, for every pair of two vertices \(s\) and \(t, t\) is reachable from \(s\) by traversing edges.
The distance between Vertex \(s\) and Vertex \(t\) is the length of a shortest path between \(s\) and \(t\).

Constraints

  • \(2 \leq N \leq 300\)
  • \(N-1 \leq M \leq \frac{N(N-1)}{2}\)
  • \(1 \leq A_{i}<B_{i} \leq N\)
  • \(1 \leq C_{i} \leq 10^{9}\)
  • \(\left(A_{i}, B_{i}\right) \neq\left(A_{j}, B_{j}\right)\) if \(i \neq j\).
  • The given graph is connected.
  • All values in input are integers.

Input

Input is given from Standard Input in the following format:

N M
A1 B1 C!
A2 B2 C2
...
AM BM CM

Output

Print the answer.

Sample Input 1

3 3
1 2 2
2 3 3
1 3 6

Sample Output 1

1

The distance between each pair of vertices before the deletion is as follows.

The distance between Vertex \(1\) and Vertex \(2\) is \(2\).
The distance between Vertex \(1\) and Vertex \(3\) is \(5\).
The distance between Vertex \(2\) and Vertex \(3\) is \(3\).
Deleting Edge \(3\) does not affect the distance between any pair of vertices. It is impossible to delete two or more edges while satisfying the condition, so the answer is \(1\).

Sample Input 2

5 4
1 3 3
2 3 9
3 5 3
4 5 3

Sample Output 2

0

No edge can be deleted.

Sample Input 3

5 10
1 2 71
1 3 9
1 4 82
1 5 64
2 3 22
2 4 99
2 5 1
3 4 24
3 5 18
4 5 10

Sample Output 3

5

解题思路

floyd

先用floyd求出每对点之间的最短路,再遍历每一条边,如果存在 \(i\)\(j\) 的路径中经过其他点的路径不大于两点之间的距离,由于距离非负,即该路径跟两点间的距离没有关系,且这条路径比这条边更优,则这条边可以删去

  • 时间复杂度:\(O(n^3+nm)\)

代码

#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")


// Problem: E - Edge Deletion
// Contest: AtCoder - AtCoder Beginner Contest 243
// URL: https://atcoder.jp/contests/abc243/tasks/abc243_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=305,inf=0x3f3f3f3f;
int d[N][N],bd[N][N],n,m;
pair<int,PII> a[90005];

int main()
{
    scanf("%d%d",&n,&m);
    memset(d,0x3f,sizeof d);
    for(int i=1;i<=n;i++)d[i][i]=0;
    int cnt=0;
    while(m--)
    {
    	int x,y,w;
        scanf("%d%d%d",&x,&y,&w);
        d[x][y]=d[y][x]=w;
        a[++cnt]={w,{x,y}};
    }
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    int res=0;
    for(int x=1;x<=cnt;x++)
    	{
    		int i=a[x].se.fi,j=a[x].se.se;
    		bool f=0;
    		for(int t=1;t<=n;t++)
    			if(t!=i&&t!=j&&d[i][t]+d[t][j]<=a[x].fi)f=1;
    		res+=f;
    	}
    printf("%d",res);
    return 0;
}
posted @ 2022-03-12 22:34  zyy2001  阅读(91)  评论(0编辑  收藏  举报