• luogu2149 [SDOI2009] Dlaxia的路线


    题目大意

      在一个无向图中,定义两个点s,t的最短路径子图为一个极大边集,对于该边集内的所有有向边e,总存在一条起点为s,终点为t且经过边e的路径,使得该路径长度为s到t的最短路径长度。现给出一个无向图,s1, s2, t1, t2四个节点,求一条最长的路径,使得它满足下列条件之一:1. 该路径上的所有边都属于s1到t1的最短路径子图且属于s2到t2的最短路径子图;2. 该路径上的所有边都属于s1到t1的最短路径子图且属于t2到s2的最短路径子图。输出该路径的长度。

    题解

      我们可以用4次Dijkstra得到s1,t1和s2,t2的最短路径子图$G_1,G_2$,另外由$G_2$可以得到其反向图$G'_2$。然后分别在子图$G_1cap G_2$和$G_1cap G'_2$上进行拓扑排序求最长路径即可。本题最重要的就是从题面到数学语言的翻译过程了,如果这一点不明确,我们可能就会建立一个子图$G_1cap(G_2cup G'_2)$,这样就乱了。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <cassert>
    using namespace std;
    
    const int MAX_NODE = 1510, MAX_EDGE = 200005, INF = 0x3f3f3f3f;
    
    struct Node;
    struct Edge;
    
    struct Node
    {
    	int DistS, DistT;
    	bool Done;
    	int Dist;//Dijkstra时,它是临时的东东;TopSort时,它是真正的最长路径长度
    	int DfsN;
    	Edge *Head;
    }_nodes[MAX_NODE];
    int TotNode;
    
    struct HeapNode
    {
    	Node *cur;
    	int Dist;
    
    	HeapNode(Node *x):cur(x),Dist(x->Dist){}
    
    	bool operator < (const HeapNode& a) const
    	{
    		return Dist > a.Dist;
    	}
    };
    
    struct Edge
    {
    	int Weight;
    	bool InSPG;//在第一个人的最短路径子图中
    	bool InTopG;//在Top子图中
    	Node *To, *From;
    	Edge *Next, *Rev;
    
    	Edge() :InTopG(false), InSPG(false){}
    }_edges[MAX_EDGE];
    vector<Edge*> Temp;
    int _eCount;
    
    Edge *NewEdge()
    {
    	if (_eCount < MAX_EDGE - 1)
    		return _edges + ++_eCount;
    	else
    	{
    		Temp.push_back(new Edge());
    		return Temp.back();
    	}
    }
    
    Edge *AddEdge(Node *from, Node *to, int w)
    {
    	Edge *e = NewEdge();
    	e->From = from;
    	e->To = to;
    	e->Weight = w;
    	e->Next = from->Head;
    	from->Head = e;
    	return e;
    }
    
    void Build(int uId, int vId, int w)
    {
    	Node *u = _nodes + uId, *v = _nodes + vId;
    	Edge *e1 = AddEdge(u, v, w), *e2 = AddEdge(v, u, w);
    	e1->Rev = e2;
    	e2->Rev = e1;
    }
    
    void Dijkstra(Node *start)
    {
    	static priority_queue<HeapNode> q;
    	for (int i = 1; i <= TotNode; i++)
    	{
    		_nodes[i].Dist = INF;
    		_nodes[i].Done = false;
    	}
    	start->Dist = 0;
    	q.push(start);
    	while (!q.empty())
    	{
    		HeapNode temp = q.top();
    		q.pop();
    		Node *cur = temp.cur;
    		if (cur->Done)
    			continue;
    		cur->Done = true;
    		for (Edge *e = cur->Head; e; e = e->Next)
    		{
    			if (cur->Dist + e->Weight < e->To->Dist)
    			{
    				e->To->Dist = cur->Dist + e->Weight;
    				q.push(e->To);
    			}
    		}
    	}
    }
    
    void GetInGraph(void(*DoInGraph)(Edge*), int spLen)
    {
    	for (int i = 1; i <= _eCount; i++)
    		if (_edges[i].From->DistS + _edges[i].Weight + _edges[i].To->DistT == spLen)
    			DoInGraph(_edges + i);
    	for (int i = 0; i < Temp.size(); i++)
    		if (Temp[i]->From->DistS + Temp[i]->Weight + Temp[i]->To->DistT == spLen)
    			DoInGraph(Temp[i]);
    }
    
    void SetOrgGraph(Edge *e)
    {
    	e->InSPG = true;
    }
    
    void MakeTopGraph1(Edge *e)
    {
    	if (e->InSPG)
    		e->InTopG = true;
    }
    
    void MakeTopGraph2(Edge *e)
    {
    	if (e->Rev->InSPG)
    		e->InTopG = true;
    }
    
    int ShortestPath(int s, int t)
    {
    	Node *start = _nodes + s, *target = _nodes + t;
    	Dijkstra(target);
    	for (int i = 1; i <= TotNode; i++)
    		_nodes[i].DistT = _nodes[i].Dist;
    	Dijkstra(start);
    	for (int i = 1; i <= TotNode; i++)
    		_nodes[i].DistS = _nodes[i].Dist;
    	return target->DistS;
    }
    
    void ClearTopGraph()
    {
    	for (int i = 1; i <= _eCount; i++)
    		_edges[i].InTopG = false;
    	for (int i = 0; i < Temp.size(); i++)
    		Temp[i]->InTopG = false;
    }
    
    stack<Node*> St;
    void Dfs(Node *cur)
    {
    	assert(cur->DfsN != 1);
    	if (cur->DfsN == 2)
    		return;
    	cur->DfsN = 1;
    	for (Edge *e = cur->Head; e; e = e->Next)
    	{
    		if (!e->InTopG)
    			continue;
    		Dfs(e->To);
    	}
    	cur->DfsN = 2;
    	St.push(cur);
    }
    
    int LongestPath()
    {
    	for (int i = 1; i <= TotNode; i++)
    	{
    		_nodes[i].Dist = 0;
    		_nodes[i].DfsN = 0;
    	}
    	for (int i = 1; i <= TotNode; i++)
    		Dfs(_nodes + i);
    	int ans = 0;
    	while (!St.empty())
    	{
    		Node *cur = St.top();
    		St.pop();
    		ans = max(ans, cur->Dist);
    		for (Edge *e = cur->Head; e; e = e->Next)
    			if (e->InTopG)
    				e->To->Dist = max(e->To->Dist, cur->Dist + e->Weight);
    	}
    	return ans;
    }
    
    int main()
    {
    	int totEdge, s1, s2, t1, t2;
    	scanf("%d%d%d%d%d%d", &TotNode, &totEdge, &s1, &t1, &s2, &t2);
    	for (int i = 1; i <= totEdge; i++)
    	{
    		int u, v, w;
    		scanf("%d%d%d", &u, &v, &w);
    		Build(u, v, w);
    	}
    	int len1 = ShortestPath(s1, t1);
    	GetInGraph(SetOrgGraph, len1);
    	int len2 = ShortestPath(s2, t2);
    	GetInGraph(MakeTopGraph1, len2);
    	int ans1 = LongestPath();
    	ClearTopGraph();
    	GetInGraph(MakeTopGraph2, len2);
    	int ans2 = LongestPath();
    	printf("%d
    ", max(ans1, ans2));
    	return 0;
    }
    

      

  • 相关阅读:
    青城的另一个一夜/情
    SystemProperties.get/set property_get/set
    锁——Java同步的基本思想
    CMUSphinx Learn
    猜数字
    我的音乐我的电影
    动态规划_钢条切割问题
    directdraw显示yuv420(YV12)
    Redis 命令参考
    HDU 3078 LCA转RMQ
  • 原文地址:https://www.cnblogs.com/headboy2002/p/9469277.html
Copyright © 2020-2023  润新知