第十五次CCFCSP认证——数据中心(SPFA变形)

题意:

题目比较繁琐,其实就是从给的图中,找出一棵树,使得这棵树最大的边尽可能小,然后求的就是这条“最大边”。

有两种解法,一是最小生成树中最大边即是答案(最小生成树采用贪心策略,每次选最小的边,那么生成的树中最大边一定是所有生成树中最大边中最小的)。二是采用spfa变形,这就和之前的地铁修建那道题一模一样(不过最后要取dis[1.2...n]中的最大值),将伸缩公式dis[to]>dis[top]+edge[i].w变成dis[to]>max(dis[top],edge[i].w),dis[to]代表从起点到达to点这条路径中的最大边,如果还有另外一条到达路径该点,并且这条路径中的最大边要小于dis[to],那么就将dis[to]更新。

代码:

#include
#include
#include
#include
#include
using namespace std;
#define inf 0x3f3f3f3f
int head[500050];
int dis[500050];
int tot;
int vis[500050];
struct Edge
{
    int to;
    int w;
    int next;
} edge[200050];
void spfa(int root)
{
    memset(dis,inf,sizeof(dis));
    queueQ;
    Q.push(root);
    dis[root]=0;
    vis[root]=1;
    int top,to;
    while(!Q.empty())
    {
        top=Q.front();
        vis[top]=0;
        Q.pop();
        for(int i=head[top];i!=-1;i=edge[i].next)
        {
            to=edge[i].to;
            if(dis[to]>max(dis[top],edge[i].w))//变形
            {
                dis[to]=max(dis[top],edge[i].w);
                if(!vis[to])
                {
                    Q.push(to);
                    vis[to]=1;
                }
            }
        }
    }
}
void addedge(int u,int v,int w)
{
    edge[tot].to=v;
    edge[tot].w=w;
    edge[tot].next=head[u];
    head[u]=tot++;
    edge[tot].to=u;
    edge[tot].w=w;
    edge[tot].next=head[v];
    head[v]=tot++;
}
int main()
{
    int n,m;
    cin>>n>>m;
    tot=0;
    int root,a,b,c;
    cin>>root;
    memset(vis,0,sizeof(vis));
    memset(head,-1,sizeof(head));
    for(int i=1; i<=m; i++)
    {
        cin>>a>>b>>c;
        addedge(a,b,c);
    }
    spfa(root);
    int res=-1;
    for(int i=1;i<=n;i++)
    {
        res=max(res,dis[i]);
    }
    cout<

你可能感兴趣的:(CCF,思维,图论)