期望得分:100+100+40=240

实际得分:100+40+0=140

 

T1 一道图论神题(god)

Time Limit:1000ms   Memory Limit:128MB

 

题目描述

LYK有一张无向图G={V,E},这张无向图有n个点m条边组成。并且这是一张带权图,只有点权。

LYK想把这个图删干净,它的方法是这样的。每次选择一个点,将它删掉,但删这个点是需要代价的。假设与这个点相连的还没被删掉的点是u1,u2,…,ukLYK将会增加a[u1],a[u2],…,a[uk]的疲劳值。

它想将所有点都删掉,并且删完后自己的疲劳值之和最小。你能帮帮它吗?

 

输入格式(god.in)

第一行两个数n,m表示一张n个点m条边的图。

第二行n个数ai表示点权。

接下来m行每行三个数u,v,表示有一条连接u,v的边。数据保证任意两个点之间最多一条边相连,并且不存在自环。

 

输出格式(god.out)

你需要输出这个最小疲劳值是多少。

 

输入样例

4 3

10 20 30 40

1 4

1 2

2 3

 

输出样例

40

 

样例解释

一个合理的方法是先删4号点,此时有10点疲劳值。接下来删3号点,获得20点疲劳值,再删2号点,获得10点疲劳值,最后删1号点,没有疲劳值。总计40点疲劳值。

 

对于30%的数据n<=10。

对于60%的数据n,m<=1000。

对于100%的数据1<=n,m,ai<=100000

 

m条边,疲劳值就会计算m次

所以可以贪心的选择 每条边的疲劳值小的点累计

正确性:如果每条无向边改为疲劳值大的点向疲劳值小的点的有向边,那么这张图就是DAG

 

#include<cstdio>
#include<algorithm>
#define N 100001
using namespace std;
int val[N];
void out(long long x)
{
    if(x/10) out(x/10);
    putchar(x%10+'0');
}
int main()
{
    freopen("god.in","r",stdin);
    freopen("god.out","w",stdout);
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    int u,v;
    long long ans=0;
    for(int i=1;i<=m;i++) 
    {
        scanf("%d%d",&u,&v);
        ans+=min(val[u],val[v]);
    }
    out(ans);
}
View Code

相关文章:

  • 2021-10-12
  • 2022-02-04
  • 2021-07-14
  • 2021-12-11
  • 2021-07-30
  • 2022-02-11
  • 2021-08-18
  • 2022-02-24
猜你喜欢
  • 2021-11-13
  • 2021-07-30
  • 2021-10-25
  • 2021-12-02
  • 2022-02-13
  • 2021-11-04
  • 2022-02-08
相关资源
相似解决方案