A1003
#include<iostream>
using namespace std;
const int maxn=501;
const int INF=100000000;
int n,m,s,e;
bool inq[maxn]={false};
int G[maxn][maxn],d[maxn],weight[maxn],w[maxn],num[maxn];
void D(int s)
{
d[s]=0;
num[s]=1;
w[s]=weight[s];
for(int i=0; i<n; i++)
{
int u=-1,MIN=INF;
for(int j=0; j<n; j++)
{
if(inq[j]==false && MIN>d[j]) //这个for是每次找当前的所有结点中值最小的,不是每次算上之前的,所以必须要判断
{
MIN=d[j];
u=j;
}
}
if(u==-1)
return ;
inq[u]=true;
for(int v=0; v<n; v++)
{
if(inq[v]==false && G[u][v]!=INF)
{
if(d[v]>d[u]+G[u][v])
{
d[v]=d[u]+G[u][v];
num[v]=num[u];
w[v]=w[u]+weight[v];
}
else if(d[v]==d[u]+G[u][v])
{
if(w[v]<w[u]+weight[v])
{
w[v]=w[u]+weight[v];
}
num[v]+=num[u];
}
}
}
}
}
int main()
{
cin >> n >> m >> s >> e;
fill(G[0],G[0]+maxn*maxn,INF);
fill(d,d+maxn,INF);
for(int i=0; i<n; i++)
{
cin >> weight[i];
}
int temp1,temp2,temp3;
for(int i=0; i<m; i++)
{
cin >> temp1 >> temp2 >> temp3;
G[temp1][temp2]=temp3;
G[temp2][temp1]=temp3;
}
D(s);
cout << num[e] << " " << w[e];
return 0;
}
A1018
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
const int maxn=510;
const int INF=10000000;
int Cmax,n,Sp,m;
int weight[maxn],G[maxn][maxn],d[maxn],minRemain=INF,minNeed=INF;
vector<int> pre[maxn];
vector<int> path,tempPath;
bool inq[maxn]={false};
void D(int s)
{
d[s]=0;
for(int i=0; i<n; i++)
{
int u=-1,MIN=INF;
for(int j=0; j<=n; j++)
{
if(inq[j]==false && d[j]<MIN)
{
MIN=d[j];
u=j;
}
}
if(u==-1)
return ;
inq[u]=true;
for(int v=0; v<=n; v++)
{
if(inq[v]==false && G[u][v]!=INF)
{
if(d[v]>d[u]+G[u][v])
{
d[v]=d[u]+G[u][v];
pre[v].clear();
pre[v].push_back(u);
}
else if(d[v]==d[u]+G[u][v])
{
pre[v].push_back(u);
}
}
}
}
}
void DFS(int v) //按照图中的例子是从下向上进行DFS,目的是通过前驱数组pre,来从有问题的站出发一直到PBMC
{
if(v==0)
{
tempPath.push_back(v);
int need=0,remain=0;
for(int i=tempPath.size()-1; i>=0; i--) //肯定是访问的这一条路上的权值,不是前驱数组
{
int id=tempPath[i];
if(weight[id]>0)
remain+=weight[id];
else
{
if(remain>abs(weight[id]))
remain-=abs(weight[id]);
else
{
need+=abs(weight[id])-remain;
remain=0;
}
}
}
if(minNeed>need)
{
minNeed=need;
path=tempPath;
minRemain=remain;
}
else if(minNeed==need && minRemain>remain)
{
minRemain=remain;
path=tempPath;
}
tempPath.pop_back();
return ;
}
tempPath.push_back(v);
for(int i=0; i<pre[v].size(); i++) //相当于进入前驱结点再次调用DFS
{
DFS(pre[v][i]);
}
tempPath.pop_back();
}
int main()
{
cin >> Cmax >> n >> Sp >> m;
for(int i=1; i<=n; i++)
{
cin >> weight[i];
weight[i]-=Cmax/2;
}
fill(G[0],G[0]+maxn*maxn,INF);
fill(d,d+maxn,INF);
int temp1,temp2,temp3;
for(int i=0; i<m; i++)
{
cin >> temp1 >> temp2 >> temp3;
G[temp1][temp2]=temp3;
G[temp2][temp1]=temp3;
}
D(0);
DFS(Sp);
cout << minNeed << " ";
for(int i=path.size()-1; i>=0; i--)
{
if(i!=path.size()-1)
cout << "->";
cout << path[i];
}
cout << " " << minRemain;
return 0;
}
题目意思:
A1030
D+DFS
#include<iostream>
using namespace std;
const int maxn=501;
const int INF=1000000000;
int G[maxn][maxn],d[maxn],c[maxn],cost[maxn][maxn],pre[maxn];
int n,m,s,e;
bool inq[maxn]={false};
void D(int s)
{
d[s]=0;
c[s]=0;
for(int i=0; i<n; i++)
{
int u=-1,MIN=INF;
for(int j=0; j<n; j++)
{
if(inq[j]==false && MIN>d[j]) //注意输入
{
MIN=inq[j];
u=j;
}
}
if(u==-1)
{
return ;
}
inq[u]=true;
for(int v=0; v<n; v++)
{
if(inq[v]==false && G[u][v]!=INF)
{
if(d[v]>d[u]+G[u][v])
{
d[v]=d[u]+G[u][v];
c[v]=c[u]+cost[u][v];
pre[v]=u;
}
else if(d[v]==d[u]+G[u][v])
{
if(c[v]>c[u]+cost[u][v])
{
c[v]=c[u]+cost[u][v];
pre[v]=u; //如果有更小的边权,需要重新统计前驱结点
}
}
}
}
}
}
void DFS(int v)
{
if(v==s) //如果题中有起点用起点表示
{
cout << v << " ";
return ;
}
DFS(pre[v]);
cout << v << " ";
}
int main()
{
cin >> n >> m >> s >> e;
int temp1,temp2,temp3,temp4;
fill(d,d+maxn,INF);
fill(G[0],G[0]+maxn*maxn,INF);
for(int i=0; i<m; i++)
{
cin >> temp1 >> temp2 >> temp3 >> temp4;
G[temp1][temp2]=temp3;
G[temp2][temp1]=temp3;
cost[temp1][temp2]=temp4;
cost[temp2][temp1]=temp4;
}
D(s);
DFS(e);
cout << d[e] << " " << c[e];
return 0;
}
D
#include<iostream>
#include<vector>
using namespace std;
const int maxn=501;
const int INF=100000000;
int n,m,s,e;
int G[maxn][maxn],d[maxn],cost[maxn][maxn],c[maxn];
bool inq[maxn]={false};
int mincost=INF;
int pre[maxn]; //直接定义一个前驱数组
void D(int s) //通过D来找到最短路径和最小边权以及用普通数组来记录的前驱结点
{
d[s]=0;
for(int i=0; i<n; i++)
{
int u=-1,MIN=INF;
for(int j=0; j<n; j++)
{
if(inq[j]==false && d[j]<MIN)
{
MIN=d[j];
u=j;
}
}
if(u==-1)
return ;
inq[u]=true;
for(int v=0; v<n; v++)
{
if(inq[v]==false && G[u][v]!=INF)
{
if(d[u]+G[u][v]<d[v])
{
d[v]=d[u]+G[u][v];
c[v]=c[u]+cost[u][v];
pre[v]=u; //令v的前驱是u
}
else if(d[u]+G[u][v]==d[v])
{
if(c[v]>c[u]+cost[u][v])
{
c[v]=c[u]+cost[u][v];
pre[v]=u; //如果能找到更小的边权还是令前驱为u
}
}
}
}
}
}
void DFS(int v) //通过递归的方式输出路径
{
if(v==s)
{
cout << v << " ";
return ;
}
DFS(pre[v]);
cout << v << " ";
}
int main()
{
cin >> n >> m >> s >> e;
int temp1,temp2,temp3,temp4;
fill(d,d+maxn,INF);
fill(G[0],G[0]+maxn*maxn,INF);
for(int i=0; i<m; i++)
{
cin >> temp1 >> temp2 >> temp3 >> temp4;
G[temp1][temp2]=temp3;
G[temp2][temp1]=temp3;
cost[temp1][temp2]=temp4;
cost[temp2][temp1]=temp4;
}
D(s);
DFS(e);
cout << d[e] << " " << c[e];
return 0;
}
1072
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=1024;
const int INF=100000004;
int G[maxn][maxn],d[maxn];
bool inq[maxn]={false};
int n,m,k,Ds;
void D(int s)
{
fill(d,d+maxn,INF);
memset(inq,false,sizeof(inq)); //上面这两个定义必须加上,只要调用D函数,就要重新定义
d[s]=0;
for(int i=0; i<n+m; i++)
{
int u=-1,MIN=INF;
for(int j=1; j<=n+m; j++)
{
if(inq[j]==false && MIN>d[j])
{
MIN=d[j];
u=j;
}
}
if(u==-1)
return ;
inq[u]=true;
for(int v=1; v<=n+m; v++)
{
if(inq[v]==false && G[u][v]!=INF)
{
if(d[v]>d[u]+G[u][v])
{
d[v]=d[u]+G[u][v];
}
}
}
}
d[s]=0;
}
int str(char s[])
{
int id=0,len=strlen(s),i=0; //strlen取字符串数组长度
while(i<len)
{
if(s[i]!='G')
{
id=id*10+s[i]-'0';
}
i++;
}
if(s[0]=='G')
return id+=n;
else
return id;
}
int main()
{
cin >> n >> m >> k >> Ds;
char temp1[5],temp2[5];
int temp3;
fill(G[0],G[0]+maxn*maxn,INF);
for(int i=0; i<k; i++)
{
cin >> temp1 >> temp2 >> temp3;
int id1=str(temp1);
int id2=str(temp2);
G[id1][id2]=temp3;
G[id2][id1]=temp3;
}
D(1);
double ansDis=-1,ansAvg=INF; //所有的最短最大距离的最大值以及对应的平均值,如果前者相同,则要最小的品均值则设置为最大
int ansId=-1;
for(int i=n+1; i<=n+m; i++) //排除距离>Ds 找出最短的最大距离 算出平均值
{
double minDis=INF,avg=0;
D(i);
for(int j=1; j<=n; j++)
{
if(d[j]>Ds)
{
minDis=-1;
break;
}
if(minDis>d[j])
{
minDis=d[j];
}
avg+=1.0*d[j]/n; //avg是double,d[j],n是int类型,所以前面*1.0
}
if(minDis==-1) //表示加油站的距离超过了所给范围,所以不在这个位置建立加油站
continue;
if(minDis>ansDis)
{
ansDis=minDis;
ansId=i;
ansAvg=avg;
}
else if(minDis==ansDis && ansAvg>avg)
{
ansId=i;
ansAvg=avg;
}
}
if(ansId==-1)
cout << "No Solution";
else
{
printf("G%d\n",ansId-n);
printf("%.1f %.1f",ansDis,ansAvg); //printf这个保留一位小数是不进行四舍五入的
//round(ansAvg*10)/10.0; 此方法可以对小数进行四舍五入保留1位小数,但是只对于小数,本题的要求也是保留1位小数,不用四舍五入
}
return 0;
}
A1087
#include<iostream>
#include<map>
#include<vector>
using namespace std;
const int maxn=300;
const int INF=1000000000;
int G[maxn][maxn],weight[maxn],d[maxn];
bool inq[maxn]={false};
int n,k,num=1,num1[maxn];
string S;
map<string,int> StringInt2;
map<int,string> IntString;
vector<int> pre[maxn];
vector<int> path,temppath;
int str(string s)
{
if(StringInt2.find(s)!=StringInt2.end())
{
return StringInt2[s];
}
else
{
StringInt2[s]=num;
IntString[num]=s;
return num++;
}
}
void D(int s)
{
d[s]=0;
num1[s]=1;
for(int i=0; i<n; i++)
{
int u=-1,MIN=INF;
for(int j=0; j<n; j++)
{
if(inq[j]==false && d[j]<MIN)
{
MIN=d[j];
u=j;
}
}
if(u==-1)
return ;
inq[u]=true;
for(int v=0; v<n; v++)
{
if(inq[v]==false && G[u][v]!=INF)
{
if(d[v]>d[u]+G[u][v])
{
d[v]=d[u]+G[u][v];
num1[v]=num1[u];
pre[v].clear();
pre[v].push_back(u);
}
else if(d[v]==d[u]+G[u][v])
{
num1[v]+=num1[u];
pre[v].push_back(u);
}
}
}
}
}
int maxhappy=-1,maxav=-1;
void DFS(int v)
{
if(v==StringInt2[S])
{
temppath.push_back(v);
int sum=0,renshu=0,tempav;
for(int i=temppath.size()-1; i>=0; i--)
{
int id=temppath[i];
sum+=weight[id];
}
tempav=sum/(temppath.size()-1);
if(maxhappy<sum)
{
maxhappy=sum;
maxav=tempav;
path=temppath;
}
else if(maxhappy==sum && tempav>maxav)
{
maxav=tempav;
path=temppath;
}
temppath.pop_back();
return ;
}
temppath.push_back(v);
for(int i=0; i<pre[v].size(); i++)
DFS(pre[v][i]);
temppath.pop_back();
}
int main()
{
cin >> n >> k >> S;
fill(G[0],G[0]+maxn*maxn,INF);
fill(d,d+maxn,INF);
StringInt2[S]=0;
IntString[0]=S;
string temp1,temp2;
int temp3;
for(int i=0; i<n-1; i++)
{
cin >> temp1 >> temp3;
int id=str(temp1);
weight[id]=temp3;
}
for(int i=0; i<k; i++)
{
cin >> temp1 >> temp2 >> temp3;
G[StringInt2[temp1]][StringInt2[temp2]]=temp3;
G[StringInt2[temp2]][StringInt2[temp1]]=temp3;
}
D(StringInt2[S]);
DFS(StringInt2["ROM"]);
cout << num1[StringInt2["ROM"]] << " " << d[StringInt2["ROM"]] << " " << maxhappy << " " << maxav << endl;
for(int i=path.size()-1; i>=0; i--)
{
if(i!=path.size()-1)
cout << "->";
cout << IntString[path[i]];
}
}