有向图最小环 floyd 和暴力bfs

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011535421/article/details/79304270

Han Solo wants to improve the reputation of the Millenium Falcon by completing more Kessel Runs! How does he complete these runs so fast? His secret is finding short cycles on the route and looping through them over and over, building up speed. Given a universe of galaxies, and 1 parsec routes that connect galaxies, find the shortest cycle in the universe.

Input Format

The first line contains two space-separated integers,  and , the number of galaxies and the number of routes. Following this are  lines, each describing a route. Each of these lines contains two space-separated integers  and ; there is a one parsec route from vertex  to vertex  in the graph. These routes are one-way.

Constraints

  • The graph is guaranteed to be simple (no self-loops or multiple edges). Note that it is possible for a cycle of length 2 to exist; that is, there may simultaneously exist edges  and .

Output Format

Print the minimum number of parsecs needed for Han to cycle. If there are no cycles in this universe, print -1.

Sample Input 0

6 7
1 2
2 3
3 4
3 1
4 5
5 6
6 3

Sample Output 0

3

Sample Input 1

4 3
1 2
2 3
2 4

Sample Output 1

-1

#include<bits/stdc++.h>
#define INF 0x3f3f3f
using namespace std;  
int mp[1005][1005]; 
int dis[1005][1005];
int n,m;  
void init()  
{  
    for(int i=1;i<=n;i++)  
    {  
        for(int j=1;j<=n;j++)  
        {  
            if(i==j)  
            {  
                mp[i][j]=0;  
                dis[i][j]=0;  
            }  
            else  
            {  
                mp[i][j]=INF;  
                dis[i][j]=INF;  
            }  
        }  
    }  
}  
int main()  
{  
    while(scanf("%d%d",&n,&m)!=EOF)  
    {  
        init(); 
        for(int i=0;i<m;i++)  
        {  
            int x,y,p;  
            scanf("%d%d",&x,&y);  
            if(mp[x][y]>1)
            {  
                mp[x][y]=1;  
                dis[x][y]=1;
            }  
        }  
        int ans=INF;  
        for(int k=1;k<=n;k++) 
        {  
            for(int i=1;i<k;i++)//标记处
            {  
                for(int j=1;j<k;j++)//标记处
                {  
                    ans=min(ans,mp[j][k]+mp[k][i]+dis[i][j]); 
                }  
            }  
            for(int i=1;i<=n;i++)  
            {  
                for(int j=1;j<=n;j++)  
                {  
                    dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
                }  
            }  
        }  
        if(ans==INF)  
        {  
            printf("-1\n");  
        }  
        else  
        {  
            printf("%d\n",ans);  
        }  
    }  
    return 0;  
} 

  1.             for(int i=1;i<k;i++)//保证i与k不相等   
  2.             {  
  3.                 for(int j=i+1;j<k;j++)//保证j和i也不相等,即i、j、k不相等   
  4.                 {  
  5.                     ans=min(ans,map[k][i]+map[k][j]+dis[i][j]);//dis[i][j]为不通过k点的i、j最短距离   
  6.                 }  
  7.             }  
杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1,那么必须满足K>2,就是说至除了出发点以外至少要经过2个其他不同的景区,而且不能重复经过同一个景区。现在8600需要你帮他找一条这样的路线,并且花费越少越好。

真草 有向图和无向图写法稍有不同 然后 这个题目可以a->b->a 所以标记处的那两个for循环不能剪枝一半 下面那段是hdu的无向图
无向图 i和j 反正能互换 而且a->b->a不算 所以要直接跳过i=j的情况
然而有向图可以a->b->c->a a->c->b->a 所以i j都要从1开始 而且本题有数据是a->b->a 所有i有可能与j相等
然后 本题边是1000 点是1000 floyd是N^3 反而不如暴力bfs N^(N+M)
暴力代码





#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>

constexpr int MAX_N = 1005;

using namespace std;

int n, m;
vector<int> adj[MAX_N];

bool vis[MAX_N];

int solve(int s) {
    memset(vis, 0, sizeof(vis));

    queue<int> to_visit;
    to_visit.push(s);

    int lvl = 0;
    while (!to_visit.empty()) {
        int sz = to_visit.size();
        for (int i = 0; i < sz; ++i) {
            int u = to_visit.front(); to_visit.pop();
            if (u == s && lvl > 0) return lvl;

            if (vis[u]) continue;
            vis[u] = true;

            for (int v : adj[u]) {
                to_visit.push(v);
            }
        }

        ++lvl;
    }

    return -1;
}

int main() {
    scanf(" %d %d", &n, &m);
    for (int i = 1; i <= m; ++i) {
        int u, v;
        scanf(" %d %d", &u, &v);
        adj[u].push_back(v);
    }

    int best = -1;
    for (int u = 1; u <= n; ++u) {
        int cur = solve(u);
        if (cur != -1) {
            if (best == -1 || cur < best) {
                best = cur;
            }
        }
    }

    printf("%d\n", best);
    
    return 0;
}

#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>

constexpr int MAX_N = 1005;

using namespace std;

int n, m;
vector<int> adj[MAX_N];

bool vis[MAX_N];

int solve(int s) {
    memset(vis, 0, sizeof(vis));

    queue<int> to_visit;
    to_visit.push(s);

    int lvl = 0;
    while (!to_visit.empty()) {
        int sz = to_visit.size();
        for (int i = 0; i < sz; ++i) {
            int u = to_visit.front(); to_visit.pop();
            if (u == s && lvl > 0) return lvl;

            if (vis[u]) continue;
            vis[u] = true;

            for (int v : adj[u]) {
                to_visit.push(v);
            }
        }

        ++lvl;
    }

    return -1;
}

int main() {
    scanf(" %d %d", &n, &m);
    for (int i = 1; i <= m; ++i) {
        int u, v;
        scanf(" %d %d", &u, &v);
        adj[u].push_back(v);
    }

    int best = -1;
    for (int u = 1; u <= n; ++u) {
        int cur = solve(u);
        if (cur != -1) {
            if (best == -1 || cur < best) {
                best = cur;
            }
        }
    }

    printf("%d\n", best);
    
    return 0;
}

暴力bfs只能用于环边长为1的情况 注意

参考 http://blog.163.com/acm_candice/blog/static/168796081201010174751374/

没有更多推荐了,返回首页