zoukankan      html  css  js  c++  java
  • CF449B Jzzhu and Cities

    CF449B Jzzhu and Cities

    题目链接

    这道题是一道比较套路的最短路的题目。

    首先,考虑一条铁路可以被取代当且仅当有另一条仅走公路的或者走不是这条铁路的路径小于等于这条铁路的长度。

    我们发现,这个过程就是在更新最短路的过程,我们先把最短路的数组 (dis[i]) 初始化为到 (i) 最短的铁路的长度,并标记为 (1),如果没有就设为正无穷。

    然后在进行 (Dijkstra) 的时候发现如果这条路可以被上面的合法情况更新,就标记为 (0)

    然后答案就是铁路总数减去仍然被标记的铁路数。

    不过需要注意的是需要在进行初始化的时候将 (dis[i]) 也压入优先队列,不过需要去一下重复的,只压入最优的,否则会 (TLE)

    #include<bits/stdc++.h>
    #define pii pair<ll,int>
    #define mp make_pair
    #define one first
    #define two second
    #define ll long long
    const int N=1e5+100,M=1e6+100;
    const ll INF=LLONG_MAX-INT_MAX;
    using std::mp;
    using std::min;
    using std::sort;
    using std::pair;
    using std::vector;
    using std::greater;
    using std::priority_queue;
    struct edge{
    	int s,e;
    	ll v;
    	int net;
    }ed[M];
    int n,m,k,tot,ans;
    int head[N];
    ll dis[N];
    bool mark[N];
    priority_queue<pii,vector<pii>,greater<pii> >q;
    inline void clear()
    {
    	for (int i=1;i<=n;i++)
    	dis[i]=INF;
    	return ;
    }
    inline void Dijkstra(int x)
    {
    	dis[x]=0;
    	q.push(mp(dis[x],x));
    	while (!q.empty())
    	{
    		pii now=q.top();
    		q.pop();
    		if (dis[now.two]!=now.one) continue;
    		for (int i=head[now.two];i;i=ed[i].net)
    		{
    			if (dis[ed[i].e]>dis[ed[i].s]+ed[i].v)
    			{
    				mark[ed[i].e]=0;
    				dis[ed[i].e]=dis[ed[i].s]+ed[i].v;
    				q.push(mp(dis[ed[i].e],ed[i].e));
    			}
    			if (dis[ed[i].e]==dis[ed[i].s]+ed[i].v) mark[ed[i].e]=0;
    		}
    	}
    	return ;
    }
    inline void add(int s,int e,ll v)
    {
    	ed[++tot]=(edge){s,e,v,head[s]};
    	head[s]=tot;
    	return ;
    }
    int main()
    {
    	scanf("%d%d%d",&n,&m,&k);
    	for (int i=1;i<=m;i++)
    	{
    		int s,e;
    		ll v;
    		scanf("%d%d%lld",&s,&e,&v);
    		add(s,e,v);add(e,s,v);
    	}
    	clear();
    	for (int i=1;i<=k;i++)
    	{
    		int e;
    		ll v;
    		scanf("%d%lld",&e,&v);
    		dis[e]=min(v,dis[e]);
    		mark[e]=1;
    	}
    	for (int i=1;i<=n;i++)
    	if (mark[i]) q.push(mp(dis[i],i));
    	Dijkstra(1);
    	for (int i=1;i<=n;i++)
    	if (mark[i]) ans++;
    	printf("%d
    ",k-ans);
    	return 0;
    }
    

    其实也可以使用 (set) 来建图来达到去除重边的目的。

    #include<bits/stdc++.h>
    #define pii pair<ll,int>
    #define mp make_pair
    #define one first
    #define two second
    #define ll long long
    const int N=1e5+100,M=1e6+100;
    const ll INF=LLONG_MAX-INT_MAX;
    using std::mp;
    using std::map;
    using std::sort;
    using std::pair;
    using std::vector;
    using std::greater;
    using std::priority_queue;
    int n,m,k,tot,ans;
    int head[N];
    ll dis[N];
    bool mark[N];
    map<int,int>ed[N];
    priority_queue<pii,vector<pii>,greater<pii> >q;
    inline ll min(ll x,ll y) {return x<y ? x:y;}
    inline void clear()
    {
    	for (int i=1;i<=n;i++)
    	dis[i]=INF;
    	return ;
    }
    inline void Dijkstra(int x)
    {
    	dis[x]=0;
    	q.push(mp(dis[x],x));
    	while (!q.empty())
    	{
    		pii now=q.top();
    		q.pop();
    		if (dis[now.two]!=now.one) continue;
    		for (map<int,int>::iterator it=ed[now.two].begin();it!=ed[now.two].end();it++)
    		{
    			int e=it->one,v=it->two;
    			if (dis[e]>dis[now.two]+v)
    			{
    				mark[e]=0;
    				dis[e]=dis[now.two]+v;
    				q.push(mp(dis[e],e));
    			}
    			if (dis[e]==dis[now.two]+v) mark[e]=0;
    		}
    	}
    	return ;
    }
    int main()
    {
    	scanf("%d%d%d",&n,&m,&k);
    	for (int i=1;i<=m;i++)
    	{
    		int s,e,v;
    		scanf("%d%d%d",&s,&e,&v);
    		map<int,int>::iterator it=ed[s].find(e);
    		if (it==ed[s].end()) ed[s].insert(mp(e,v));
    		else it->two=min(it->two,v);
    		it=ed[e].find(s);
    		if (it==ed[e].end()) ed[e].insert(mp(s,v));
    		else it->two=min(it->two,v);
    	}
    	clear();
    	for (int i=1;i<=k;i++)
    	{
    		int e,v;
    		scanf("%d%d",&e,&v);
    		dis[e]=min(v,dis[e]);
    		mark[e]=1;
    		q.push(mp(dis[e],e));
    	}
    	Dijkstra(1);
    	for (int i=1;i<=n;i++)
    	if (mark[i]) ans++;
    	printf("%d
    ",k-ans);
    	return 0;
    }
    
  • 相关阅读:
    How to Start Up an Open Source Company
    How Open Source Became The Default Business Model For Software
    Refactoring open source business models
    Open Source Isn't A Business Model, It's A Market Strategy
    11 open source business models
    5 Successful Business Models for Web-Based Open-Source Projects
    35 Top Open Source Companies
    golang实现php里的serialize()和unserialize()序列和反序列方法
    Laravel修炼:服务提供者
    使用 swoole_process 实现 PHP 进程池
  • 原文地址:https://www.cnblogs.com/last-diary/p/11693846.html
Copyright © 2011-2022 走看看