HIT暑期集训 图论基础

C    CodeForces 938D

建图+最短路。新建一个特别的节点,每个城市与这个特别节点之间加上一条长为该城市停留的花费a的边;然后对于题目给出每条边,将长度设置为原来长度乘以2(因为需要一来一回两次)加入图中。这样从新建节点到每个城市的最短路就是题目所求的最短花费了。用堆优化dij求单源最短路就行了。(好像新学了一点重载运算符相关的东西)

(最近好像一直因为数组开错WA题。。啊这真是)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxn 200005
#define maxm 600005
#define inf 1e13
using namespace std;
typedef long long ll;
int num,to[maxm],nxt[maxm],last[maxn],vis[maxn],n,m;
ll w[maxm],dis[maxn];
struct node
{
    int num;
    ll dis;
    node(int x,ll y)
    {
        num=x;dis=y;
    }
    bool operator < (const node &a)const{return dis>a.dis;}
    //重载运算符< 
};
priority_queue<node>q;
void add(int x,int y,ll z)
{
    to[++num]=y;
    nxt[num]=last[x];
    last[x]=num;
    w[num]=z;
}
void dij(int s)
{
    int i,x,y;
    for (i=1;i<=n+1;i++) 
    {
        dis[i]=inf;vis[i]=0;
    }
    dis[s]=0;
    q.push(node(s,0));
    while (!q.empty())
    {
        x=q.top().num;
        q.pop();
        if (vis[x]) continue;
        vis[x]=1;
        for (i=last[x];i;i=nxt[i])
        {
            y=to[i];
            if (dis[x]+w[i]<dis[y]) 
            {
                dis[y]=dis[x]+w[i];
                q.push(node(y,dis[y]));
            }
        }
    }
}
int main()
{
    int i,j,x,y;
    ll z;
    scanf("%d%d",&n,&m);
    for (i=1;i<=m;i++)
    {
        scanf("%d%d%lld",&x,&y,&z);
        add(x,y,2*z);
        add(y,x,2*z);
    }
    for (i=1;i<=n;i++)
    {
        scanf("%lld",&z);
        add(n+1,i,z);
    }
    dij(n+1);
    for (i=1;i<=n;i++) printf("%lld ",dis[i]);
    return 0;
}

G    LibreOJ 2610

对图求最大生成树,对于每组询问找LCA即可。(学着用了倍增求LCA,以为代码会比树链剖分短,但并没有。。)

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 10005
#define maxm 100005
#define inf 99999999
using namespace std;
int w[maxn][22],fa[maxn][22],dep[maxn],vis[maxn];
int num,to[maxm],nxt[maxm],last[maxn],wei[maxm];
int f[maxn];
struct edge
{
    int from,to,w;
}e[maxm];
bool cmp(edge x,edge y){return x.w>y.w;}
void add(int x,int y,int z)
{
    to[++num]=y;
    nxt[num]=last[x];
    last[x]=num;
    wei[num]=z;
}
int find(int x)
{
    if (x==f[x]) return x;
    return f[x]=find(f[x]);
}
void dfs(int x)
{
    int i,y;
    vis[x]=1;
    for (i=last[x];i;i=nxt[i])
    {
        y=to[i];
        if (vis[y]) continue;
        dep[y]=dep[x]+1;
        w[y][0]=wei[i];
        fa[y][0]=x;
        dfs(y);
    }
}
int lca(int x,int y)
{
    if (find(x)!=find(y)) return -1;
    int i,ans=inf;
    if (dep[x]>dep[y]) 
    {
        i=x;x=y;y=i;
    }
    for (i=20;i>=0;i--)
        if (dep[fa[y][i]]>=dep[x])
        {
            ans=min(ans,w[y][i]);
            y=fa[y][i];
        }    
    if (x==y) return ans;
    for(i=20;i>=0;i--)
    {
        if(fa[x][i]!=fa[y][i])
        {
            ans=min(ans,w[x][i]);
            ans=min(ans,w[y][i]);
            x=fa[x][i];
            y=fa[y][i];
        }
    }
    ans=min(ans,w[x][0]);
    ans=min(ans,w[y][0]);
    return ans;
}
int main()
{
    int i,j,x,y,fx,fy,n,m,q;
    scanf("%d%d",&n,&m);
    for (i=1;i<=m;i++) scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].w);
    
    sort(e+1,e+m+1,cmp);
    for (i=1;i<=n;i++) f[i]=i;
    for (i=1;i<=m;i++)
    {
        x=e[i].from;
        y=e[i].to;
        fx=find(x);
        fy=find(y);
        if (fx!=fy)
        {
            f[fx]=fy;
            add(e[i].from,e[i].to,e[i].w);
            add(e[i].to,e[i].from,e[i].w);
        }
    }
    
    for (i=1;i<=n;i++)
    {
        if (vis[i]) continue;
        dep[i]=1;
        fa[i][0]=i;
        w[i][0]=inf;
        dfs(i);
    }
    for (i=1;i<=20;i++)
        for (j=1;j<=n;j++)
        {
            fa[j][i]=fa[fa[j][i-1]][i-1];
            w[j][i]=min(w[j][i-1],w[fa[j][i-1]][i-1]);
        }
    scanf("%d",&q);
    while (q--)
    {
        scanf("%d%d",&x,&y);
        printf("%d\n",lca(x,y));
    }
    return 0;
}

H    UVA 11354

I    UVA 10269

posted @ 2020-08-12 10:19  lsy_kk  阅读(166)  评论(0)    收藏  举报