上午:
9:00-9:05 日常签到;
9:05-12:15 看数据结构与算法慕课网课(看完第三章线性表);
下午:
12:30-15:00 看数据结构与算法慕课网课(第四章树);
16:00-19:00 刷题(拓扑排序);
今天回顾了之前学过的一些数据结构与算法,对于栈与队列,二叉树有了系统的认知(可能是之前学得比较零散),刷题的时候学会了解决多权值的最短路径问题,拓扑排序。
栈和队列用于解决有特定顺序的线性表问题,栈是先进后出,队列是先进先出,可以用链表实现也可以用数组模拟,为了提高使用率还可以用循环链表。后缀表达式的求值就是栈的一个很好的应用,当表达式里出现括号时要注意其优先级最高,只有遇到右括号时左括号才会出栈。多权值的最短路径问题https://vjudge.net/contest/357138#problem/C哇,读到这个题,心想求最短路径和最小花费,直接两边DijkstraOK,直接WA。后来想想,先要保证路径最短,那么就先求最短路径,Dijkstra不变,只不过最后更新的时候处理一下最小花费就行了,具体处理方法见代码。另外,既然存在路径相同而花费不同,那么必然输入数据存在两顶点相同,路径相同,但花费不同的数据,所以输入的时候我们只保留相同情况下花费最小即可。
void dijkstra(int start)
{
for(int i=1;i<=n;i++)
{
dis[i]=map[start][i];
v[i]=value[start][i];
book[i]=0;
}
book[start]=1;
for(int i=1;i<=n;i++)
{
int min=INF,k;
for(int j=1;j<=n;j++)
if(!book[j]&&dis[j]<min)
min=dis[k=j];
book[k]=1;
for(int j=1;j<=n;j++)
{
if(dis[j]>dis[k]+map[k][j])
{
dis[j]=dis[k]+map[k][j];
v[j]=v[k]+value[k][j];
}
else if(dis[j]==dis[k]+map[k][j]&&v[j]>v[k]+value[k][j])
v[j]=v[k]+value[k][j];
}
}
}
int main()
{
int a,b,c,p,m;
while(cin>>n>>m)
{
if(m==0&&n==0)
break;
memset(map,INF,sizeof(map));
memset(value,INF,sizeof(value));
for(int i=0;i<m;i++)
{
cin>>a>>b>>c>>p;
if(c<map[a][b])
{
map[a][b]=map[b][a]=c;
value[a][b]=value[b][a]=p;
}
if(c==map[a][b]&&value[a][b]>p)
value[b][a]=value[a][b]=p;
}
int s,t;
scanf("%d%d",&s,&t);
dijkstra(s);
printf("%d %d\n",dis[t],v[t]);
}
}
拓扑排序:在一个有向图中,对所有的节点进行排序,要求没有一个节点指向它前面的节点。先统计所有节点的入度,对于入度为0的节点就可以分离出来,然后把这个节点指向的节点入度减一,直到所有节点都被分离出来。
void topsort(int v)
{
for(int i=1;i<=v;i++)
for(int j=1;j<=v;j++)
if(map[i][j])
rudu[j]++;
int k;
for(int i=1;i<=v;i++)
{
for(int j=1;j<=v;j++)
{
if(rudu[j]==0)
{
k=j;
break;
}
}
path[i]=k;//存入数组稍后输出
rudu[k]=-1;//入度为0,存入数组后将其赋为-1
for(int j=1;j<=v;j++)//遍历,将与其相关的节点入度减一
{
if(map[k][j])
rudu[j]--;
}
}
}