hdu3873 Invade the Mars 有限制的最短路

  此段略过。看完题目,觉得这真的是一道好题目。自己有想法,但是实现起来却很难。看题解,写代码,然后写题解,意义何在?我不认为自己总是这么弱。就算抄代码,我也要有自己的理解。菜鸟总会成长。

  首先,题目必须读懂。起点是1,终点是n,并且一定有解。对于一个点(城市),如果它有魔法保护,必须解除对它的所有提供保护,才能占领它。但是在占领该城市之前,军队可以把它围起来(等待友军去破环魔法阵),并且军队进入城市的时间是忽略的。也就是说占领该城市所需的时间只是行军的时间和解除该城市的魔法所需的时间有关,并且是这两者中的大的一个。还有一点,i城市没被攻破,军队只能停留,不能前进。

  具体实现:用一个数组pt记录某城市被保护的次数(城墙的耐久度)。当pt[i]==0时,并且该城市没有被占领,那么军队占领该城市的时间dist[i]=max(dist[i], dn[i]),其中dn[i]表示该城市脱离保护的时间(也就是该城市可能被占领的最小时间)。此时,如果j城市(未被占领)与i城市相邻,则dist[j]=dist[i] + w, w是e[i][j]的边权。这样就有一个大致的模型了。还要注意,在确定i城市被占领的时间的时候,要判断军队是否能到达i城市。也就是判断dist[i]!=INF?

  为了避免dist[]不断松弛,需要用优先队列。每次弹出来的点能保证是到达该点的最短距离。当某点不收保护时,就入队。最短距离如果已经确定,就标记,不用再去更新距离(其实无法更新,因为已经是最短距离)。

  在知道i点的最短距离后,去计算相邻的j点的最短距离时。需要dist[i]和i。因为是按照最短距离的大小而弹出队列的,dist[i]需要入队。占领i城市以后,它所保护的城市将不再收到它的保护。需要枚举。所以需要将i入队。然后就用了pair函数。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
typedef pair<long long , int > pii;
const int N = 3010, M=100010;
const int INF = 0x3f3f3f3f;
struct node
{
    int to, w,next;
};
node edge[M];
int head[N], pt[N];//
long long dist[N], dn[N];
bool vis[N];
int tot;
vector<int> p[N];
void SPFA(int s, int n )
{
    int i,k;
    for(i=0;i<=n;i++) dist[i]=INF;
    memset(vis,0,sizeof(vis));
    priority_queue<pii,vector<pii>,greater<pii> > q;
    while(!q.empty()) q.pop();
    dist[s]=0;
    q.push(make_pair(dist[s],s));
    while(!q.empty())
    {
        pii u=q.top(); q.pop();
        int x=u.second;
        if(vis[x]) continue;
        vis[x]=1;
        int y=p[x].size();
        k=0;
        while(k<y)
        {
            int z=p[x][k];
            pt[z]--;
            dn[z]=max(dn[z],dist[x]);
            if(dist[z]!=INF&&pt[z]==0)
            {
                dist[z]=max(dn[z],dist[z]);
                q.push(make_pair(dist[z],z));
            }
            k++;
        }
        for(k=head[x];k!=-1;k=edge[k].next)
        {
            int v=edge[k].to;
            if(dist[v]>dist[x] + edge[k].w)
            {
                dist[v]=max(dist[x]+edge[k].w, dn[v]);
                if(!pt[v]) q.push(make_pair(dist[v],v));
            }
        }
    }
}
void addedge(int i,int j,int w)
{
    edge[tot].to=j;
    edge[tot].w=w;
    edge[tot].next=head[i];
    head[i]=tot++;
}
void init(int n)
{
    tot=0;
    memset(head,-1,sizeof(head));
    memset(dn,0,sizeof(dn));
    for(int i=1;i<=n;i++)
        p[i].clear();
}
int main()
{
    //freopen("test.txt","r",stdin);
    int cas,i,j,k,n,m,T,c,w;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d%d",&n,&m);
        init(n);
        for(k=0;k<m;k++)
        {
            scanf("%d%d%d",&i,&j,&w);
            addedge(i,j,w);
        }
        for(i=1;i<=n;i++)
        {
            scanf("%d",&k);
            pt[i]=k;
            while(k--)
            {
                scanf("%d",&j);
                p[j].push_back(i);
            }
        }
        SPFA(1,n);
        printf("%I64d\n",dist[n]);
    }
    return 0;
}

  首先

时间: 2024-08-02 02:04:08

hdu3873 Invade the Mars 有限制的最短路的相关文章

HDU 3873 Invade the Mars(带限制条件的Dijkstra)

题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=3873 思路: 军队可以先等待在城市外面,等保护该城市的城市都被攻破后,直接进城(即进城不用耗费时间).则进入该城市的最少时间为max(达到该城市的最少时间,到达保护该城市的所有城市的最大时间). 用num[i]标记第i个城市被保护的数目,只有当该点被保护的数目为0时,才能入S集合,从而优化到其他点的时间.当前进入S集合的城市,遍历它所保护的城市,num[i]减一,记录下被保护的城市解除保护所需的最长

题单二:图论500

http://wenku.baidu.com/link?url=gETLFsWcgddEDRZ334EJOS7qCTab94qw5cor8Es0LINVaGMSgc9nIV-utRIDh--2UwRLvsvJ5tXFjbdpzbjygEdpGehim1i5BfzYgYWxJmu ==========  以下是最小生成树+并查集=========================[HDU]1213         How Many Tables        基础并查集★1272         小

图论五百题!

生死看淡不服就淦,这才是人生! =============================以下是最小生成树+并查集======================================[HDU]1213 How Many Tables 基础并查集★1272 小希的迷宫 基础并查集★1325&&poj1308 Is It A Tree? 基础并查集★1856 More is better 基础并查集★1102 Constructing Roads 基础最小生成树★1232 畅通工程 基

图论 500题——主要为hdu/poj/zoj

转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并查集======================================[HDU]1213   How Many Tables   基础并查集★1272   小希的迷宫   基础并查集★1325&&poj1308  Is It A Tree?   基础并查集★1856   More i

图论精炼500题

忘了从哪转的了... =============================以下是最小生成树+并查集====================================== [HDU] 1213               How Many Tables                    基础并查集★ 1272               小希的迷宫                     基础并查集★ 1325&&poj1308    Is It A Tree?       

hdu图论题目分类

=============================以下是最小生成树+并查集====================================== [HDU] 1213 How Many Tables 基础并查集★ 1272 小希的迷宫 基础并查集★ 1325&&poj1308 Is It A Tree? 基础并查集★ 1856 More is better 基础并查集★ 1102 Constructing Roads 基础最小生成树★ 1232 畅通工程 基础并查集★ 123

【转载】夜深人静写算法(四)——差分约束

[转载]夜深人静写算法(四) - 差分约束  目录     一.引例       1.一类不等式组的解   二.最短路       1.Dijkstra       2.图的存储       3.链式前向星       4.Dijkstra + 优先队列       5.Bellman-Ford       6.SPFA       7.Floyd-Warshall   三.差分约束        1.数形结合        2.三角不等式        3.解的存在性        4.最大值

【司雨寒】最短路专题总结

最近在刷郏老大博客上的最短路专题 [HDU] 1548            A strange lift                    基础最短路(或bfs) 1 //#define LOCAL 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 using namespace std; 6 7 const int maxn = 200 + 10; 8 struct Point 9

图论500题

=============================以下是最小生成树+并查集====================================== [HDU] 1213   How Many Tables   基础并查集★ 1272   小希的迷宫   基础并查集★ 1325&&poj1308  Is It A Tree?   基础并查集★ 1856   More is better   基础并查集★ 1102   Constructing Roads  基础最小生成树★ 12