1. 程式人生 > 實用技巧 >校內模擬測試010T1 刪點遊戲dt

校內模擬測試010T1 刪點遊戲dt

題意簡述

n個點m條邊的無向圖,要把所有點一個一個地刪去。每次刪去一個點的花費為這個點相鄰的還未被刪除的點的點權。無重邊無自環,求最小代價。

資料範圍

對於\(30\%\)的資料\(n \le 10\)

對於\(60\%\)的資料\(n,m \le 1000\)

對於\(100\%\)的資料\(1\le n,m,a_i\le100000\)

分析

如果從點的角度來考慮,是無法得出貪心的結果的。考慮將點權轉化為邊權。

可以發現,最後每一條邊都是要被刪去的。刪掉一個點的代價是它的鄰點,而對於一條邊,我們肯定要貪心地讓其刪去的代價最小。故刪去一條邊的代價為連線的兩個點的最小值。

Code

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#define re register
#define debug printf("Now is %d\n",__LINE__);
using namespace std;

template<class T>inline void read(T&x)
{
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    x=ch-'0';ch=getchar();
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
}
inline int read()
{
	int x=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    x=ch-'0';ch=getchar();
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    return x;
}
int G[55];
template<class T>inline void write(T x)
{
    int g=0;
    if(x<0) x=-x,putchar('-');
    do{G[++g]=x%10;x/=10;}while(x);
    for(re int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
LL n,m,ans;
LL a[100010]; 
int main()
{
	n=read();
	m=read();
	for(re LL i=1;i<=n;i++) a[i]=read();
	for(re LL i=1;i<=m;i++)
	{
		ans+=min(a[read()],a[read()]);
	}
	cout<<ans;
	return 0;
}