记一次讲题

第一次给学弟学妹讲题,紧张到语无伦次。

好不容易看到两个学妹感觉要被我劝退了。

半个小时讲完图论基础快到不可思议,当场裂开。

我后知后觉发现自己在念经(bushi)

啊啊啊啊啊啊我不要讲题啦啊啊啊啊啊。

好的现在我发现两个学妹走了,真就当场劝退了555555

(以下是课上提到的例题

hdu2363 Cycling

题意:给定一个n个点m条边的图,图中每个点都有一个高度h,

求在保证路径中的结点的最大和最小高度之差最小的情况下,从1到n的最小高度差和最短路。

思路:带限制的最短路 枚举路径中的最大高度和最小高度,跑最短路。

(可以先把所有的最大最小高度的组合根据高度差从小到大排序,从高度差小的开始枚举

在求最短路的过程中,如果结点的高度h不在枚举的范围内,就跳过。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=105;
const int maxm=10005;
const int inf=2e9;
int n,num,to[maxm],nxt[maxm],last[maxn],vis[maxn];
int w[maxm],dis[maxn],h[maxn];
struct hi
{
    int dh,l,h;
}a[5005];
bool cmp(hi x,hi y){return x.dh<y.dh;}
struct node
{
    int num;
    int dis;
    node(int x,int 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,int z)
{
    to[++num]=y;
    nxt[num]=last[x];
    last[x]=num;
    w[num]=z;
}
int dij(int low,int high,int s,int t)
{
    int i,x,y;
    for (i=1;i<=n;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;
        if (x==t) return dis[t];
        vis[x]=1;
        for (i=last[x];i!=-1;i=nxt[i])
        {
            y=to[i];
            if (h[y]<low || h[y]>high) continue;
            if (dis[x]+w[i]<dis[y]) 
            {
                dis[y]=dis[x]+w[i];
                q.push(node(y,dis[y]));
            }
        }
    }
    return dis[t];
}
int main()
{
    int i,j,m,T,x,y,z,re,tmp,ans,dist,cnt;
    int low,high,lim_low,lim_high;
    scanf("%d",&T);
    while (T--)
    {
        num=0;
        memset(last,-1,sizeof(last));
        scanf("%d%d",&n,&m);
        for (i=1;i<=n;i++) scanf("%d",&h[i]);
        while (m--)
        {
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
            add(y,x,z);
        }
        lim_low=min(h[1],h[n]);
        lim_high=max(h[1],h[n]);
        ans=0;
        dist=0;
        cnt=0;
        for (i=1;i<=n;i++)
        for (j=i+1;j<=n;j++)
            if (h[i]>h[j])
            {
                a[++cnt].dh=h[i]-h[j];
                a[cnt].l=h[j];
                a[cnt].h=h[i];
            }
            else 
            {
                a[++cnt].dh=h[j]-h[i];
                a[cnt].l=h[i];
                a[cnt].h=h[j];
            }
        sort(a+1,a+cnt+1,cmp);
        for (i=1;i<=cnt;i++)
        {
            low=a[i].l;
            high=a[i].h;
            tmp=high-low;
            if (lim_low<low || high<lim_high) continue;
            if (ans!=0 && tmp>ans) break; 
            re=dij(low,high,1,n);
            if (re!=inf) 
            {
                if (ans==0 || re<dist)
                {
                    ans=tmp;
                    dist=re;
                }
            }
        }    
        printf("%d %d\n",ans,dist);
    }
    return 0; 
}
hdu2363

poj3013 Big Christmas Tree

题意:给一张图,图中的每个点和每条边都有对应权值。

要求构造一棵以1为根的生成树,使得所有边的代价之和最小。 定义边的代价=边权 * 边的所有后代节点的点权之和 0 ≤n,m≤ 50000

思路: 虽然题目中提到构造生成树,但这其实是一题最短路。

仔细一想,∑(边权*子树点权和)=∑(点权*点到根路径上的边权和)。 所以就变成了单源最短路问题。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const ll inf=1e18;
const int maxn=50005;
int n,num,to[maxn<<1],nxt[maxn<<1],last[maxn],vis[maxn];
ll w[maxn<<1],dis[maxn],val[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;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!=-1;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 T,m,i,x,y,flag;
    ll ans,z;
    scanf("%d",&T);
    while (T--)
    {
        num=0;
        memset(last,-1,sizeof(last));
        scanf("%d%d",&n,&m);
        for (i=1;i<=n;i++) scanf("%d",&val[i]);
        while (m--)
        {
            scanf("%d%d%lld",&x,&y,&z);
            add(x,y,z);
            add(y,x,z);
        }
        dij(1);
        ans=0;
        flag=0;
        for (i=1;i<=n;i++) 
            if (dis[i]==inf)
            {
                flag=1;
                break;
            } 
            else ans+=dis[i]*val[i];
        if (!flag) printf("%lld\n",ans);
        else printf("No Answer\n");
    }
    return 0;
} 
poj3013

 

posted @ 2020-12-05 14:11  lsy_kk  阅读(133)  评论(0编辑  收藏  举报