您的位置:首页 > 其它

POJ 3013 【需要一点点思维...】【乘法分配率】

2015-09-27 10:40 218 查看
题意:

(这题明显感觉自己是英语渣)

给n个点从1到n标号,下面一行是每个点的权,另外给出m条边,下面是每条边的信息,两个端点+权值,边是无向边。你的任务是选出一些边,使这个图变成一棵树。这棵树的花费是这样算的,1号固定为树根,树中每个双亲节点下面的边都有个单价(即边权),然后单价乘上这条边的下面所有的子孙后代的点权和(COPY FROM:http://www.cnblogs.com/scau20110726/archive/2013/05/06/3063401.html)

思路:

题目说每个点都要用上,这时候画个图,想想乘法分配率...

坑点:

这道题的dis默认的inf值要稍大一些...

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
int n,m;
int tmp[50005];
const long long inf=199999999999999;
long long dis[50005];
bool vis[50005];
struct edge
{
int id;
int mint;
edge *next;
};
edge edges[100500];
edge *adj[50005];
int ednum;
inline void addEdge(int a,int b,int c)
{
edge *tmp;
tmp=&edges[ednum];
ednum++;
tmp->id=b;
tmp->mint=c;
tmp->next=adj[a];
adj[a]=tmp;
}
bool SPFA()
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
dis[i]=inf;
}
queue<int>q;
q.push(1);
vis[1]=1;
dis[1]=0;
while(!q.empty())
{
int tmp=q.front();
q.pop();
vis[tmp]=0;
for(edge *p=adj[tmp];p;p=p->next)
{
if(p->mint+dis[tmp]<dis[p->id])
{
dis[p->id]=p->mint+dis[tmp];
if(!vis[p->id])
{
q.push(p->id);
vis[p->id]=1;
}
}
}
}
for(int i=1;i<=n;i++)
{
if(dis[i]==inf)
return 0;
}
return 1;
}
long long cal()
{
long long rel=0;
for(int i=1;i<=n;i++)
{
rel+=((long long )dis[i])*tmp[i];
}
return rel;
}
int main()
{
int t,a,b,c;
scanf("%d",&t);
for(int tt=1;tt<=t;tt++)
{
ednum=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
adj[i]=NULL;
}
for(int i=1;i<=n;i++)
{
scanf("%d",&tmp[i]);
}
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
addEdge(a,b,c);
addEdge(b,a,c);
}
if(SPFA())
{
printf("%I64d\n",cal());
}
else
{
printf("No Answer\n");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: