「日常訓練」「小專題·圖論」Domino Effect(1-5)

SamHX發表於2018-08-06

題意

分析

這題幾乎就是一條dijkstra的問題。但是,如何考慮倒在中間?
要意識到這題求什麼:單源最短路的最大值。那麼有沒有更大的?倒在中間有可能會使它更大。
但是要注意一個問題:不要把不存在的邊(邊長為inf)算進去;另外,n=1的情況需要注意。

程式碼

// Origin:
// Theme: Graph Theory (Basic)
// Date: 080618
// Author: Sam X

//#include <bits/stdc++.h>
#include <iostream>
#include <utility>
#include <iomanip>
#include <cstring>
#include <cmath>
#define MP make_pair
#define PB push_back
#define fi first
#define se second
#define ZERO(x) memset((x), 0, sizeof(x))
#define ALL(x) (x).begin(),(x).end()
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define per(i, a, b) for (int i = (a); i >= (b); --i)
#define QUICKIO                  \
    ios::sync_with_stdio(false); \
    cin.tie(0);                  \
    cout.tie(0);
using namespace std;
typedef long long ll;
typedef unsigned long long ul;
typedef pair<int,int> pi;
typedef pair<int,pi> pii;

int dist[505][505];
int main()
{
    int n,m,kase=0;
    while(cin>>n>>m)
    {
        if(!n && !m) break;
        memset(dist,0x3f,sizeof(dist));
        rep(i,1,n) dist[i][i]=0;
        rep(i,1,m)
        {
            int x,y,z; cin>>x>>y>>z;
            dist[x][y]=dist[y][x]=z;
        }
        if(n==1)
        {
            cout<<"System #"<<++kase<<"\nThe last domino falls after 0.0 seconds, at key domino 1.\n\n";
            continue;
        }
        int d[505]; memset(d,0x3f,sizeof(d));
        d[1]=0;
        bool vis[505]; ZERO(vis);
        rep(i,1,n)
        {
            int mind=0x3f3f3f3f,x=-1;
            rep(j,1,n) if(!vis[j] && d[j]<mind) mind=d[x=j];
            if(x==-1) break;
            vis[x]=true;
            rep(i,1,n)
            {
                d[i]=min(d[i],d[x]+dist[x][i]);
            }
        }
        //rep(i,1,n) cout<<d[i]<<" "; cout<<endl;
        double ans=-1,ans_mid=-1;
        int end=-1,lend=-1,rend=-1,maxd=-1;
        bool ismid=false;
        rep(i,2,n)
        {
            if(d[i]>ans)
            {
                ans=d[end=i];
            }
            //maxd=max(d[i],maxd);
        }

        rep(i,1,n)
        {
            rep(j,i+1,n)
            {
                if(dist[i][j]==0x3f3f3f3f) continue;
                double tmp=(d[i]+d[j]+dist[i][j])/2.0;
                if(tmp>ans_mid)
                {
                    lend=i; rend=j;
                    ans_mid=max(tmp,ans_mid);
                }
            }
        }
        ismid=ans_mid-ans>1e-8;
        cout<<"System #"<<++kase<<endl<<"The last domino falls after "<<fixed<<setprecision(1)<<double(ismid?ans_mid:ans)<<" seconds, ";
        if(!ismid)
        {
            cout<<"at key domino "<<end<<"."<<endl;   
        }
        else
        {
            cout<<"between key dominoes "<<lend<<" and "<<rend<<"."<<endl; 
        }
        cout<<endl;
    }
    return 0;
}

相關文章