UVA10917 路径统计

来源:互联网 发布:yum wget 编辑:程序博客网 时间:2024/06/04 21:15

关键词:DAG图上s到t的路径统计

求s到t特殊路径统计,路径上每条边<u,v>满足dt[u]>dt[v],dt[i]是i到达t的最短路。

满足dt[u]<dt[v]的路径一定是DAG图,因此问题化归为统计DAG图上s->t的路径数目

1.统计DAG图上任意一点到达t的路径数目

num[i]:i到达t的路径数目,由DAG图的dp性质,num[u]+=num[v],v是u的后继。

<span style="font-size:14px;">void dfs(int u,int t){//DAG图上的dp过程 含记忆化搜索思想    if(num[u]) return;    for(int i=0;i<g[u].size();i++){        int v=g[u][i].to,w=g[u][i].w;        if(d[v]<d[u]) { dfs(v,t),num[u]+=num[v]; }    }    if(u==t) num[u]=1;//特殊条件}</span>

2.统计DAG图上s到达任意一点的路径数目


技巧:在原图上通过限制条件来遍历新图,而不必真的建立新图

建立反图G‘,问题化归为1。如果直接在原图上进行dfs,则不能求出num的真实值。因为对于u的前继v,在使用边<u,v>之前还未求出num[v]的真实值。

只有利用dfs的回溯才能实现DAG图的dp性质

<span style="font-size:14px;">#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#include<vector>#include<stack>#include<queue>#define ll long long#define INF 0x3f3f3f3f#define maxn 1010#define mem(a,b) memset(a,b,sizeof(a))using namespace std;int n,m;struct Edge{ int to,w; };vector<Edge> g[maxn];int vis[maxn],d[maxn],parent[maxn];int num[maxn];//i到达t的路径数目 dp[u]+=dp[v];struct Heapnode{    int u,d;    bool operator< (const Heapnode& rhs)const{        return d>rhs.d;    }};void add(int u,int v,int w){ g[u].push_back((Edge){v,w}); }void dij(int s){    priority_queue<Heapnode> que;    for(int i=1;i<=n;i++) d[i]=INF;//d和vis的初始化    d[s]=0,mem(vis,0);    que.push((Heapnode){s,0});//队列初始化    while(!que.empty()){        Heapnode x=que.top();que.pop();//取d最小的元素        int u=x.u;        if(vis[u]) continue;//判断是否在S集合中        vis[u]=1;        for(int i=0;i<g[u].size();i++){//松弛            int v=g[u][i].to,w=g[u][i].w;            if(d[v]>d[u]+w){                d[v]=d[u]+w;                que.push((Heapnode){v,d[v]});            }        }    }}void dfs(int u,int t){//DAG图上的dp过程 含记忆化搜索思想    if(num[u]) return;    for(int i=0;i<g[u].size();i++){        int v=g[u][i].to,w=g[u][i].w;        if(d[v]<d[u]) { dfs(v,t),num[u]+=num[v]; }    }    if(u==t) num[u]=1;//特殊条件}void build(){    scanf("%d",&m);    for(int i=1;i<=n;i++) g[i].clear();    for(int i=1;i<=m;i++){        int a,b,c;        scanf("%d%d%d",&a,&b,&c);        add(a,b,c),add(b,a,c);    }}int main(){    //freopen("a.txt","r",stdin);    while(scanf("%d",&n)!=EOF&&n){        build();        dij(2);        mem(num,0);        dfs(1,2);        printf("%d\n",num[1]);    }}</span><strong style="font-size:18px;"></strong>


0 0
原创粉丝点击