【模拟7.19】那一天她离我而去(最短路,估价函数剪枝)

这题忘记输出-1,wa0了QAQ

首先这题我先看的第二题数据范围,n==m意味着只有一个环,所以可以用tarjan的算法

把环判出来,比较简单。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<stack>
 8 #include<vector>
 9 #define ll long long
10 using namespace std;
11 #define MAXN 80010
12 #define ps push_back
13 struct node{int to,n,w;}e[MAXN];int tot=0;int head[MAXN];
14 void add(int u,int v,int w){e[++tot].to=v;e[tot].n=head[u];e[tot].w=w;head[u]=tot;}
15 int vis[MAXN],low[MAXN],dfn[MAXN];
16 vector<int>sum[MAXN];int de=0;
17 int belong[MAXN];
18 int n,m;int fa[MAXN];
19 stack<int>q;int cnt=0;int ans_w=10000000;
20 void tarjan(int x,int w)
21 {
22      low[x]=dfn[x]=++de;vis[x]=1;q.push(x);
23      for(int i=head[x];i;i=e[i].n)
24      {
25         int to=e[i].to;
26         if(dfn[to]==0)
27         {
28             fa[to]=x;   
29             tarjan(to,w+e[i].w);
30             low[x]=min(low[x],low[to]);
31         }
32         else if(vis[to]&&fa[x]!=to)
33         {
34             if(to==1)
35             {
36                 ans_w=min(ans_w,w+e[i].w);
37             }
38             low[x]=min(low[x],dfn[to]);
39         }
40      }
41      if(dfn[x]==low[x])
42      {
43          int top=0;
44          cnt++;
45          do
46          {
47             top=q.top();q.pop();vis[top]=0;
48             sum[cnt].ps(top);
49             belong[top]=cnt;
50          }
51          while(x!=top);
52      }
53 }
54 int T;
55 int main()
56 {
57     scanf("%d",&T);
58     while(T--)
59     {
60         ans_w=100000000;
61         memset(head,0,sizeof(head));tot=0;
62         memset(vis,0,sizeof(vis));
63         memset(low,0,sizeof(low));
64         memset(dfn,0,sizeof(dfn));
65         scanf("%d%d",&n,&m);       
66         for(int i=1;i<=m;++i)
67         {                                              
68             int x,y,w;
69             scanf("%d%d%d",&x,&y,&w);
70             add(x,y,w);add(y,x,w);
71         }
72         tarjan(1,0);
73         for(int x=1;x<=cnt;++x)
74         {
75             for(int i=0;i<sum[x].size();++i)
76             {
77                 int to=sum[x][i];
78             }
79         }
80         if(ans_w==100000000)printf("-1
");
81         else printf("%d
",ans_w);
82         for(int i=1;i<=cnt;++i)sum[i].clear();
83         cnt=0;
84     }
85 }
30分代码,神犇不要看

满分的话听了skyh大佬的讲评后用估价函数剪枝DFS,然后暴力跑

注意DFS中标记的是边而不是点(想起来tarjan的割桥)

因为他点可以重复经过,边不能

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<stack>
 8 #include<vector>
 9 #include<queue>
10 #define MAXN 41010
11 #define ps push_back
12 #define ll int
13 using namespace std;
14 struct node{ll to,n,w;}e[2*MAXN];
15 ll tot=0;ll head[MAXN];
16 void add(ll u,ll v,ll w){e[++tot].to=v;e[tot].n=head[u];e[tot].w=w;head[u]=tot;}
17 bool bian[2*MAXN];
18 ll dis[MAXN];
19 priority_queue< pair<ll,ll> >q;
20 ll ans_w=0;
21 ll n,m;
22 void SPFA(ll top)
23 {
24     memset(bian,0,sizeof(bian));
25     dis[top]=0;q.push(make_pair(0,top));bian[top]=1;
26     while(!q.empty())
27     {
28        ll x=q.top().second;q.pop();
29        for(ll i=head[x];i;i=e[i].n)
30        {
31            ll to=e[i].to;
32            if(dis[to]>dis[x]+e[i].w)
33            {
34                dis[to]=dis[x]+e[i].w;
35                if(bian[to]==0)
36                {
37                   q.push(make_pair(-dis[to],to));
38                   bian[to]=1;
39                }
40            }
41        }
42     }
43 }
44 void DFS(ll x,ll w)
45 {
46     if(w+dis[x]>=ans_w)return ;
47     if(x==1)
48     {
49         if(w!=0)
50         {
51             ans_w=min(ans_w,w);
52             return ;
53         }
54     }
55     for(ll i=head[x];i;i=e[i].n)
56     {
57        ll to=e[i].to;
58        if(bian[i]==1)continue;
59        bian[i]=1;bian[(i^1)]=1;
60        DFS(to,w+e[i].w);
61        bian[i]=0;bian[(i^1)]=0;
62     }
63 }
64 ll T;
65 int main()
66 {
67     scanf("%d",&T);
68     while(T--)
69     {
70         ans_w=0x7ffffff;tot=1; 
71         memset(head,0,sizeof(head));
72         memset(dis,0x7f,sizeof(dis));
73         scanf("%d%d",&n,&m);       
74         for(ll i=1;i<=m;++i)
75         {                                              
76            ll x,y,w;
77            scanf("%d%d%d",&x,&y,&w);
78            add(x,y,w);add(y,x,w);
79         }
80         SPFA(1);
81         memset(bian,0,sizeof(bian));
82         DFS(1,0);
83         if(ans_w==0x7ffffff)
84           printf("-1
");
85         else
86           printf("%d
",ans_w);
87     }
88 }
View Code
原文地址:https://www.cnblogs.com/Wwb123/p/11221089.html