打工人上人 (25 分)

代码长度限制 16 KB
时间限制 1000 ms
内存限制 64 MB

题目描述

总所周知,联通的路由之间经常会出现故障。keven正在峡谷之巅快乐,无空维护路由之间的最短路,那么请你帮他回答所有的询问。

首先给出一个网络,现简化为无向连通图,有 n 个路由, m 条边组成,且每条边长均为1。

会出现3种如下操作:

操作1:A,B 两个路由间的通路断开。
操作2:A,B 两个路由间的通路连接。
操作3:询问 A,B 间的最短路。

输入格式

第一行三个整数 n,m,q(1<=n<=100,1<=m<=n∗(n−1)/2,1<q<=10000)

接下来 m 行,每行 A,B 两个整数表示 A,B 间有一条通路

接下来 q 行,每行 op,A,B 三个整数,对应上述操作

保证所有输入合法,不出现重边、自环。

输出格式

您需要按顺序回答每次操作3,如果联通输出最短路的大小,否则输出-1

输入样例

3 3 8
3 2
1 2
3 1
3 2 3
3 1 3
1 2 3
3 3 2
3 2 1
1 1 3
2 2 3
3 1 3

输出样例

1
1
2
1
2

个人思路

  1. 可以看出是无向图的最短路径问题,常用算法就是Dijkstr和folyd,用folyd的3个for循环加上指令输入的一个循环,时间复杂度过大
  2. 尝试了用dfs依然时间超限,也在意料之中
  3. 所以这里只能考虑迪杰斯特拉算法,进一步说明见代码注释
#include<bits/stdc++.h>
using namespace std;
#define MAX 0x3f3f3f


int n,m,q;
int ans[110][110];//存储无向图
int disk[110];//标记最短路径
bool marked[110];//标记某一个点是否已被确定为最小路径

void Disk(int r)//迪杰斯特拉算法,r这里表示起止位置
{
    
    
    for(int i=1;i<=n;i++)
    {
    
    
        disk[i]=ans[r][i];//利用图初始化最短路径
        marked[i]=false;//将所有点都初始化为未被标记
    }
    marked[r]=true;//标记当前起始位置
    for(int i=1;i<=n;i++)//保证所有的点能被访问到的点都能被访问到
    {
    
    
        int index=0;//初始化下标和最小值
        int min=MAX;
        for(int j=1;j<=n;j++)//找到r到(1-n)之间没被标记过的最小的那个点
        {
    
    
            if(!marked[j]&&disk[j]<min)
            {
    
    
                index=j;//不断更新最小的路径值和下标
                min=disk[j];
            }
        }
        if(index!=0)//可以找到最小路径则标记被找到的点已访问
        {
    
    
            marked[index]=true;
        }
        //对刚标记的下标为index的点进行可访问点遍历
        for(int j=1;j<=n;j++)
        {
    
    
        		//更新下标为index的点可访问点的最短路径
            if(!marked[j]&&disk[j]>min+ans[index][j])
            {
    
    
                disk[j]=min+ans[index][j];
            }
        }
    }
}

int main()
{
    
    
    cin>>n>>m>>q;
    for(int i=0;i<=n;i++)//初始化,自身到自身值为0
    {
    
    
        disk[i]=MAX;
        marked[i]=false;
        for(int j=0;j<=n;j++)
        {
    
       
            if(i==j)
                ans[i][j]=0;
            else
                ans[i][j]=MAX;
        }
    }
    while(m--)
    {
    
    
        int t,r;//根据输入建图
        cin>>t>>r;
        ans[t][r]=1;
        ans[r][t]=1;
    }
    while(q--)
    {
    
    
        int cmd,r,t;//指令输入,操作r到t
        cin>>cmd>>r>>t;
        if(cmd==3)
        {
    
    
        		//对起始点r用迪杰斯特拉算法找到最r到其他点的最短路径
            Disk(r);
            
            if(disk[t]>=MAX)
            {
    
    
                cout<<"-1"<<endl;
            }
            else
            {
    
    
                cout<<disk[t]<<endl;
            }
        }
        else if(cmd==1)
        {
    
    
            ans[r][t]=MAX;
            ans[t][r]=MAX;
        }
        else if(cmd==2)
        {
    
    
            ans[t][r]=1;
            ans[r][t]=1;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_46050495/article/details/123963013