zoukankan      html  css  js  c++  java
  • hdu 1317+hdu 1535(SPFA)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1317

    思路:只要在SPFA中将一个条件,就不会进入负环。那么如果有正环呢,显然退出条件是某个点入队列次数>=n,此时退出时只需判断当前点是否与n存在路径,这步可以用Floyd来实现。。。

    View Code
     1 #include<iostream>
     2 #include<queue>
     3 const int MAXN=110;
     4 using namespace std;
     5 int n;
     6 int weight[MAXN];
     7 int power[MAXN];
     8 int _count[MAXN];//记录某点的入队列次数
     9 bool map[MAXN][MAXN];
    10 bool reach[MAXN][MAXN];//floyd判断任何两点是否可达
    11 
    12 
    13 void Floyd(){
    14     for(int k=1;k<=n;k++){
    15         for(int i=1;i<=n;i++){
    16             for(int j=1;j<=n;j++){
    17                 reach[i][j]=(reach[i][j]
    18                 ||(reach[i][k]&&reach[k][j]));
    19             }
    20         }
    21     }
    22 }
    23 
    24 bool SPFA(int now){
    25     queue<int>Q;
    26     Q.push(now);
    27     memset(power,0,sizeof(power));
    28     memset(_count,0,sizeof(_count));
    29     power[1]=100;
    30     while(!Q.empty()){
    31         int now=Q.front();
    32         Q.pop();
    33         _count[now]++;
    34         if(_count[now]>=n)return reach[now][n];//如果某个点的次数超过n次,那么说明存在正环,此时只要判断这点到n点是否可达就行了
    35         for(int next=1;next<=n;next++){
    36             if(map[now][next]&&power[now]+weight[next]>power[next]
    37             &&power[now]+weight[next]>0){
    38                 Q.push(next);
    39                 power[next]=power[now]+weight[next];
    40             }
    41         }
    42     }
    43     return power[n]>0;
    44 }
    45 
    46 int main(){
    47     while(~scanf("%d",&n)&&n!=-1){
    48         memset(map,false,sizeof(map));
    49         memset(reach,false,sizeof(reach));
    50         for(int i=1;i<=n;i++){
    51             int num;
    52             scanf("%d%d",&weight[i],&num);
    53             for(int j=1;j<=num;j++){
    54                 int k;
    55                 scanf("%d",&k);
    56                 map[i][k]=true;
    57                 reach[i][k]=true;
    58             }
    59         }
    60         Floyd();
    61         if(!reach[1][n]){
    62             printf("hopeless\n");
    63         }else {
    64             if(SPFA(1)){
    65                 printf("winnable\n");
    66             }else 
    67                 printf("hopeless\n");
    68         }
    69     }
    70     return 0;
    71 }

     题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1535

    思路:正向建一次图,反向建一次图,然后两次SPFA就可以了,采用vector的邻接表形式,特别好用。。。

    View Code
     1 #include<iostream>
     2 #include<vector>
     3 #include<queue>
     4 const int MAXN=1000000+10;
     5 typedef long long ll;
     6 const ll inf=1e60;
     7 using namespace std;
     8 struct Node{
     9     int v,w;
    10 };
    11 vector<Node>mp1[MAXN];//正向建图
    12 vector<Node>mp2[MAXN];//反向建图
    13 int n,m;
    14 ll cost[MAXN];
    15 
    16 void SPFA(int u,vector<Node>mp[]){
    17     for(int i=2;i<=n;i++)cost[i]=inf;
    18     cost[1]=0;
    19     queue<int>Q;
    20     Q.push(u);
    21     while(!Q.empty()){
    22         int u=Q.front();
    23         Q.pop();
    24         for(int i=0;i<mp[u].size();i++){
    25             int v=mp[u][i].v;
    26             int w=mp[u][i].w;
    27             if(cost[v]>cost[u]+w){
    28                 cost[v]=cost[u]+w;
    29                 Q.push(v);
    30             }
    31         }
    32     }
    33 }
    34 
    35 
    36 int main(){
    37     int _case;
    38     scanf("%d",&_case);
    39     while(_case--){
    40         scanf("%d%d",&n,&m);
    41         for(int i=1;i<=n;i++){
    42             mp1[i].clear();
    43             mp2[i].clear();
    44         }
    45         for(int i=1;i<=m;i++){
    46             int u,v,w;
    47             scanf("%d%d%d",&u,&v,&w);
    48             Node p1,p2;
    49             p1.v=u,p2.v=v,p1.w=p2.w=w;
    50             mp1[u].push_back(p2);
    51             mp2[v].push_back(p1);
    52         }
    53         SPFA(1,mp1);//正向求一次
    54         ll ans=0;
    55         for(int i=2;i<=n;i++){
    56             ans+=cost[i];
    57         }
    58         SPFA(1,mp2);//反向求一次
    59         for(int i=2;i<=n;i++){
    60             ans+=cost[i];
    61         }
    62         printf("%lld\n",ans);
    63     }
    64     return 0;
    65 }
    66 
    67         
  • 相关阅读:
    apollo-springboot 整合使用
    axon 过滤存储哪些事件
    springtools 解决lombok
    mylog 自定义注解打印 logger
    java高级应用:线程池全面解析
    监控 Java 线程池运行状态
    线程池获当前使用的活跃线程数
    JVM调优总结 -Xms -Xmx -Xmn -Xss(1)
    java高并发之线程池
    Nginx 网络事件
  • 原文地址:https://www.cnblogs.com/wally/p/3018609.html
Copyright © 2011-2022 走看看