题解 P5096 【[USACO2004OPEN]Cave Cows 1 洞穴里的牛之一】

· · 题解

看到不少大佬都用状压DP过的,

但是,

凭良心估计一下自己的实力,发现本蒟蒻并不会啊……

重新思考一下,设dis[i][j]表示从i到j的最短边(限制收集)的长度。N<=100,可以用floyd处理。

最后贪心一下,把有干草的点i按照dis[1][i]排序,从最小的开始选。

蒟蒻水平低,还望各位大佬斧正。

#include<cstdio>
#include<algorithm>
#define res register int
using namespace std;

const int inf=23333333;
int n,m,k;
int dis[110][110];
int a[110],b[110];

template<class T>
inline void read(T& v)
{
    char c=getchar();v=0;
    while(c<'0'||c>'9'){c=getchar();}
    while(c>='0'&&c<='9'){v=(v<<3)+(v<<1)+(c^'0');c=getchar();}
}

inline void floyd()
{   
    for(res i=1;i<=n;i++)dis[i][i]=inf;

    for(res t=1;t<=n;t++)
     for(res i=1;i<=n;i++)
      for(res j=1;j<=n;j++)
      {
          dis[i][j]=dis[j][i]=max(dis[i][j],min(dis[i][t],dis[t][j]));
            //考虑是否要从t点绕行(因为是无向图,且无次数限制,可以随便走) 
      }
}

inline int solve()
{
    for(res i=1;i<=k;i++)b[i]=dis[1][a[i]];

    sort(b+1,b+k+1);

    int ans=0;

    for(res i=1;i<=k;i++)//贪心在这里 
    if(b[i]>ans)//当前已经拥有ans个,判断是否能够从这走。 
    {
        ans++;
    }

    return ans;
}

int main()
{   
    read(n),read(m),read(k);

    for(res i=1;i<=k;i++)
        read(a[i]);

    int x,y,w;
    for(res i=1;i<=m;i++)
    {
        read(x),read(y),read(w);
        dis[x][y]=dis[y][x]=max(dis[x][y],w);
    }

    floyd();

    printf("%d",solve());

    return 0;
}