POJ 3921 - DFSID

     同样是<ACM国际大学生程序设计竞赛亚洲区域真题题解>上的一题...本题的解法听说有网络流...构了一下没构出来..而且听说构图跑最大流的解法并不完备...存在Bug...所以还是搜了...DFSID神马的还是超级给力啊...907MS压线水过...

     开始的时候各种超时...一个很重要的原因就是提供的点为50..但边有4000条...显然所需的信息里两个点有一条边和两个点有 N条边是一回事...将冗余的边通通剔除...所以我干脆就用个邻接表来整了...还有就是搜索当前条件下从1~n的最短时间..也没必要用dijkstra和SPFA..反而效率低..因为每条边长相等...直接BFS就行了...

      枚举当前删点个数 ...判断在删除小于等于这么多点的条件下能否使1~n的最短时间大于k...所以每次找出最短路..枚举删去这条路上的一个点.. 再继续找最短路..知道删点个数到达所卡的个数...或者1~n找不到路径了...再判断....


Program:

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<map>
#include<queue>
#include<stack>
#define ll long long
#define oo 1000000000
#define pi acos(-1)
using namespace std;     
int n,m,k,pre[55];
bool note[55],arc[55][55];
queue<int> myqueue;
bool BFS()
{
     int h,i,dis[55];
     memset(dis,0x7f,sizeof(dis)); 
     while (!myqueue.empty()) myqueue.pop(); 
     myqueue.push(1);
     dis[1]=0; 
     while (!myqueue.empty())
     {
             h=myqueue.front();
             myqueue.pop();  
             if (h==n) break; 
             for (i=1;i<=n;i++)
                if (arc[h][i] && !note[i] && dis[i]>oo)
                {
                       dis[i]=dis[h]+1; 
                       pre[i]=h;
                       myqueue.push(i); 
                } 
     } 
     if (dis[n]>k) return true;
     return false;
}
bool FindAns(int p)
{ 
     int way[55],i,m;
     if (BFS()) return true;
     if (!p)    return false;
     i=pre[n];
     m=0;
     while (i!=1)
     {
             way[++m]=i;
             i=pre[i];
     }
     for (i=m;i>=1;i--) 
     {
             note[way[i]]=true;
             if (FindAns(p-1)) return true;
             note[way[i]]=false;
     }
     return false;
}
int main()
{ 
     int p,x,y,ans;
     while (~scanf("%d%d%d",&n,&m,&k))
     {
             if (!n && !m && !k) break; 
             memset(arc,false,sizeof(arc));
             while (m--)
             {
                     scanf("%d%d",&x,&y); 
                     arc[x][y]=true;      
             }    
             for (ans=0;ans<n;ans++)
             {
                     memset(note,false,sizeof(note));
                     if (FindAns(ans)) break;
             }
             printf("%d\n",ans); //r
     }
     return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值