• SGU 145.Strange People(无环K短路)


    时间:0.25s
    空间:4m

    题意:

         其实就是求无环第K短路。
         
    

    输入:

         给出n,m,k,分别代表,n个点,m条边,第k长路。
         接下来m行,三个整数x,y,z,分别代表x,y之间有条费用为x的双向路。保证没有重边。
    

    输出:

        第一行两个数a,b,第k小费用a,和经过的点的个数b。
        接下来b个数,代表第k短的路径。
    


    Sample Input

     

     5 10 3
     1 2 6
     1 3 13
     1 4 18
     1 5 35
     2 3 14
     2 4 34
     2 5 17
     3 4 22
     3 5 15
     4 5 34
     1 5
    

    Sample Output

     

     35 2 
     1 5




    Solution:
    求k短路的算法,基本都是A*,这里的数据量比较小,可以采用二分答案。
    二分路径的长度,DFS求出有多少条路径的长度小于它,如果是(k-1)的话直接输出。


    PS:sgu在这一题上数据似乎出了问题,很多人都PE没法AC,我试着提交别人AC过的代码还是pe。
    因此代码没有AC,但对程序的正确性有把握。

    参考代码:
    #include <cstdio>
    const int INF = 111;
    int g[INF][INF], vis[INF], path[INF];
    int n, m, k, x, y, z, l, r, mid, leSum;
    int S, T, pd, len, tol;
    void dfs (int x, int dis) {
    	vis[x] = 1;
    	if (x == T) {
    		if (dis < mid)  leSum++;
    		if (!pd && dis == mid) leSum++, pd = 1;
    	}
    	else
    		for (int i = 1; i <= n; i++)
    			if (!vis[i] && g[x][i] && dis + g[x][i] <= mid)
    				dfs (i, dis + g[x][i]);
    	vis[x] = 0;
    }
    int check (int x) {
    	pd = leSum = 0;
    	dfs (S, 0);
    	return leSum;
    }
    int getPath (int x, int dis) {
    	vis[x] = 1;
    	if (x == T && dis == len) {
    		path[++tol] = x;
    		return pd = 1;
    	}
    	else
    		for (int i = 1; i <= n; i++) {
    			if (!vis[i] && g[x][i] && g[x][i] + dis <= len) {
    				if (getPath (i, dis + g[x][i]) ) path[++tol] = x;
    				if (pd) return 1;
    			}
    		}
    	vis[x] = 0;
    }
    int Search () {
    	while (l <= r) {
    		mid = l + (r - l >> 1);
    		int tem = check (mid);
    		if (tem == k)
    			return mid;
    		else if (tem > k)
    			r = mid - 1;
    		else l = mid + 1;
    	}
    	return -1;
    }
    int main() {
    	scanf ("%d %d %d", &n, &m, &k);
    	for (int i = 1; i <= m; i++) {
    		scanf ("%d %d %d", &x, &y, &z);
    		g[x][y] = g[y][x] = z, r += z;
    	}
    	scanf ("%d %d", &S, &T);
    	len = Search();
    	pd = tol = 0;
    	getPath (S, 0);
    	printf ("%d %d
    ", len, tol);
    	for (int i = tol; i > 1; i--)
    		printf ("%d ", path[i]);
    		printf("%d
    ",path[1]);
    	return 0;
    }
    

      

    
    

      

    
    
  • 相关阅读:
    sqlplus中var和print的使用
    sqlplus中break命令的使用
    android之OptionsMenu
    android之TabHost(下)
    android之TabHost(上)
    android之dialog
    android之listview
    android开发事件监听
    决策树ID3算法示例
    回溯法-设置碉堡
  • 原文地址:https://www.cnblogs.com/keam37/p/3841250.html
Copyright © 2020-2023  润新知